The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME
       Perl6::Contexts - array and hash variables turn into ref-
       erences to themselves when used in non-numeric scalar con-
       text or as function arguments

SYNOPSIS
         my @foo = ( 1 .. 20 );
         my $foo = @foo;                  # same as my $foo = \@foo;
         my $foo = 0 + @foo;              # unchanged - length of @foo
         $obj->some_method(10, 20, @foo); # same as $obj->some_method(10, 20, \@foo);
         some_function(10, 20, @foo);     # same as some_function(10, 20, \@foo);

DESCRIPTION
       Perl6::Contexts makes Perl 5 behave more like Perl 6 with
       reguard to the meaning of array and hash variables when
       used in scalar context and function calls.

       Using this module to make Perl 5 more like Perl 6 won't go
       very far towards writing Perl 5 that will run under Perl 6
       but it will help you get used to some of the changes. (As
       far as legacy code is concerned, check out the excellent
       PONIE project - everyones money is on PONIE!).

       This module doesn't add new syntax - it merely changes the
       meaning of existing syntax.

       Context

       Perl 6 divides scalar context into boolean, numeric,
       string, and object context, among others.

       Reference Context

       Arrays and hashes used in reference context turn into a
       reference to themselves.  We assume reference context
       unless we know better. This vaguely approximates Perl 6's
       behavior. For example, given a completely spurrious "my
       $foo = @bar", we assume that $foo should be a reference to
       @bar.

       Numeric Context

       Arrays used in numeric context return their size, as in
       Perl 5.  Perl 6 uses the "+" prefix or "num", "int", or
       "float" keywords to force numeric context.  We don't have
       those keywords (yet), but "+" and "scalar" do the trick
       for now.  Numeric context is also supplied by math related
       operators such as "-", "*", "sin", and so on.

       Force numeric context to get the old Perl 5 behavior of
       counting the elements in an array or hash:

         scalar @arr;
         0 + @arr;

       In Perl 6, the 0 is redundant and undesireably ugly but it
       is required for our purposes so I suggest using "scalar"
       instead.

       Note that hashes return internal memory allocation infor-
       mation when used in scalar context - use "scalar keys
       %hash" to count the number of items it contains.

       Boolean Context

       Boolean context formalizes the murky semantics of "zero
       but true" for Perl 6 but our implementation doesn't do
       anything to help with that.  Our boolean context is cur-
       rently identical to Perl 5's scalar context which is iden-
       tical to numeric context and is provided by "and", "or",
       "&&", "||", and other conditionls.

       String Context

       Perl 6 gives arrays, hashes, and objects, among other
       things, control over how they present themselves when used
       as a string.  Perl 6 adds interpolation of hashes in
       quoted text, along with the arrays and scalars that
       already interpolate in Perl 5.  Each variable can be
       extended with a trait to control the exact details of its
       presentation.  Perl 5 allows a minimal amount of presenta-
       tion control with the global $" variable.  See perldoc
       perlvar's entry on $" for details.  We don't try to inter-
       polate hashes in strings but we do "join" on $" to
       stringify arrays when used as a string. The "." operator,
       for example, forces string context.

         use Perl6::Contexts;
         my $t1; my $t2; my $t3;
         my @arr = ( 1 .. 20 );
         print '@arr: ' . @arr . "\n";  # note that . is used instead of comma

       "." forces string context on @arr in this example.

       Or:

         use Perl6::Contexts;
         my $t1; my $t2; my $t3;
         my @arr = ( 1 .. 20 );
         $" = '-';
         @arr =~ m/15-16/ or die;

       "=~" forces string context on @arr in this example. That's
       a lot more useful than matching on a string representing
       of the number of things in @arr.

       Yes, the "my $t1" things are needed to use arrays in
       string context. It's a long story.  See the BUGS section
       for details if you're curious but it's a limitation I hope
       to overcome soon. There must be one such variable allo-
       cated for each string context use of an array in the sin-
       gle most complex expression in the module (and thus is the
       sacrifice that must be paid homage to satisify the demons
       that make this module work).

       Context Summary

       This module cheats a bit in guessing context. Contexts do
       not propogate (yet) as they do in Perl. Operators such as
       "||" do not yet apply the context to their operands that
       they themselves got from somewhere. The point of some con-
       texts, such as boolean, is entirely missed. In general,
       the Perl 6 rules and this module come closer to the ideal
       of "do what I mean".

       Function Calls

       Hashes and arrays as function and method call arguments
       don't flatten by default. Perl 6 uses the splat operator,
       "*", to flatten arrays and hashes sent as arguents to
       functions.  Like Perl 6, we don't flatten implicitly
       either. Unlike Perl 6, explicit flattening is kind of
       painful.

         use Perl6::Contexts;

         my @numbers = map int rand 100, 1 .. 100;
         sub_that_wants_a_bunch_of_numbers(@numbers);   # passes by reference - wrong
         sub_that_wants_a_bunch_of_numbers(\@numbers);  # same thing - wrong

       In order to flatten things for subroutines that actually
       want flattened arrays, use one of these tricks:

         sub_that_wants_a_bunch_of_numbers(@numbers[0 .. $#numbers]);
         sub_that_wants_a_bunch_of_numbers(@numbers->flatten());

       "->flatten()" requires autobox. See below. Perl 6's "*"
       operator, which forcefully unflattens arrays, is not
       available in Perl 5 or via this module.

       Subroutines called by code subjected to the rules of
       Perl6::Contexts must accept references to arrays and
       hashes unless the array or hash in the call to that sub-
       routine was explicitly flattened:

         use Perl6::Contexts;

         my @array = ( 1 .. 20 );
         sub_that_wants_an_array_ref(@array);

         sub sub_that_wants_an_array_ref {
             my $arrayref = shift;   # @array turned into a reference
             my @array = @$arrayref; # or use an autobox trick if you like
         }

       This applies even if the subroutine or method is in
       another package entirely.  Note that the requirement that
       @$arrayref be written that way and not $arrayref is an
       incompleteness of this module though obviously we aren't
       going to munge modules that don't use us.  See the autobox
       tricks below and of course $arrayref may be used directly
       as the array reference that it is.

       autobox Interopation

       This module works with autobox. Normally autobox requires
       a reference, a scalar, a number, a string, or a code ref-
       erence, which excludes arrays and hashes:

         use autobox;
         use autobox::Core;
         my @arr = ( 1 .. 20);
         @arr->sum->print;     # doesn't work without Perl6::Contexts
         (\@arr)->sum->print;  # works without Perl6::Contexts but ugly

       Same goes for hashes.  (While this is a fluke side effect
       of what we're doing I was aware of the consequence early
       on and it was a great motiviation to create this module,
       so autobox integration is a feature beyond any doubt.)

       Often you'll want arrays and hashes to flatten when passed
       as arguments:

         use Perl6::Contexts;

         my @numbers = map int rand 100, 1 .. 100;
         sub_that_wants_a_bunch_of_numbers(@numbers);  # passes by reference - wrong

       autobox and autobox::Core may be used to force array flat-
       tening:

         use Perl6::Contexts;
         use autobox;
         use autobox::Core;

         my @numbers = map int rand 100, 1 .. 100;
         sub_that_wants_a_bunch_of_numbers(@numbers->flatten);  # explicit flattening

       To accomplish this without autobox, you may take a slice
       of the entire array:

         use Perl6::Contexts;

         my @numbers = map int rand 100, 1 .. 100;
         sub_that_wants_a_bunch_of_numbers(@numbers[0 .. $#numbers]); # ugly but works

BUGS
       There are no meaningful texts at this time. That's on the
       top of the list for 0.2. Consider this a preview release.

       autobox::Core makes assumptions about what Perl 6 will
       name autoboxed methods on primtive types. As I learn more
       (and more is published) these examples and autobox::Core
       will change to be consistent with Perl 6. In other words,
       do not rely on the interface staying the same until ver-
       sion 1.0 (and then you're taking your own chances but I'll
       try my best).

       Scalar variables used in conditionals (such as "if" and
       "and") don't dereference themselves and reference values
       are always true (unless you do something special). Hence
       this will always die:

         use Perl6::Contexts;
         my @arr = ( );      # completely empty arrays evaluate false
         my $arrref = @arr;  # takes a reference
         die if $arrref;     # always dies - ERROR

       You must use " autobox " and " autobox::Core " and write
       "die if $arrref->flatten()", or else write the old Perl 5
       stand by,  @$arrref .

       "push", "pop", "exists", "delete", "shift", "unshift",
       "sort", "map", "join", and "grep" issue compile time warn-
       ings when used on a scalar even though this scalar could
       only possibly be a reference.

         push $arrref, 1;

         # diagnostic: Type of arg 1 to push must be array (not scalar dereference)

       Perl 6 handles this correctly. Perl 5 could with replace-
       ment versions of those statements written in Perl. Perhaps
       in the next version this module will.  Of course, it would
       be nice if the core did the "right thing" ;)

       The unary "*" operator doesn't flatten lists as it does in
       Perl 6.  Instead, autobox and "->flatten" must be used for
       this, or synonymously, "->elements".

       "scalar" is considered to provide numeric context. This is
       not consistent with Perl 6, where "string", "bool", "bit",
       "string", "int", "num", and "float" generate contexts,
       much like "scalar" does in Perl 5. This module should
       export those keywords.

       While "0 + @arr" accidentally works to put @arr in numeric
       context and get its length, no unary "~" (yet) exists to
       force string context (though it could - it would mean no
       more negating strings full of bits without calling a func-
       tion in another module to do it).

       "my @array = $arrayref" should, but doesn't, dereference
       $arrayref and dump its contents into @array. This can, and
       should, be done but I haven't gotten to it yet.

       Hashes in strings should interpolate but that's outside
       the scope of this module.  See Perl6::Interpolators for an
       implementation.

       Making users create temporaries is a kludge as ugly as
       any. I plan to roll this ability into B::Generate.  Why
       are "my $t1", "my $t2", and so on, required?  Perl associ-
       ates nameless lexical variables with operations to speed
       up the stack machine.  Each operation has its own virtu-
       ally private scalar value, array value, hash value, or so
       on, that it can push to the stack any time it likes with-
       out having to allocate it. Next time the instruction runs
       again it knows that it can reuse the same variable.
       B::Generate isn't able to allocate these for instructions
       so I have to use preexisting named variables.

VERSION
       0.1. Versions fixing bugs I've found and adding features I
       think of will increment the minor version number. 1.0 will
       be released after a sufficient amount of user feedback
       suggestions that I'm not as far off in la-la land as I
       might be for all I know.  This la-la land caveat applies
       to the Perl 6 specification as well, which I am
       doubtlessly botching.  Version 1.0 will also include
       proper tests.

SEE ALSO
       autobox associates methods with primitive types allowing
       more complex APIs for types than would be reasonable to
       create built-in functions for. autoboxing also simplifies
       complex expressions that would require a lot of parenthe-
       sis by allowing the expression to be arranged into more a
       logical structure.

       autobox::Core compliments autobox with wrappers for most
       built-in functions, some statements, some functionalish
       methods from core modules, and some Perl 6-ish things.

       Perl 6 is able to take $arrayref[0] to mean
       "$arrayref.[0]" which is "$arrayref->[0]" in Perl 5. This
       module won't get you that but see Perl6::Variables.

       Want gives Perl 5 subroutines Perl 6-like information
       about the context they execute in, including the number of
       result values expected, boolean context, "BOOL", and
       various kinds of reference contexts. It is a generalized
       replacement for the built-in wantarray function.

       B represents Perl internal data structures (including and
       especially bytecode instructions for the virtual machine)
       as Perl objects within perl itself. B::Generate extends B
       with the capability to modify this bytecode from within
       the running program (!!!). This module uses these two mod-
       ules to do what it does. Opcode served as a reference, and
       code was stolen from B::Utils, B::Deparse, and B::Concise
       (but with implicit permission - yes, Free Software pro-
       grammers do steal but never uninvited - seriously, I owe a
       debt of gratitude to those whose work I've built on, espe-
       cially Simon Cozens and Malcolm Beattie in this case).

       http://perldesignpatterns.com/?PerlAssembly attempts to
       document the Perl internals I'm prodding so bluntly.

AUTHOR
       SWALTERS, scott@slowass.net