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