sub foo($x, $y, $z) {...} # expects three scalars
@onetothree = 1..3; # array stores three scalars
foo(1,2,3); # okay: three args found
foo(@onetothree); # error: only one arg
foo(*@onetothree); # okay: (array) flattened to three args
The * operator flattens lazily -- the array is only flattened if
flattening is actually required within the subroutine. To flatten
before the list is even passed into the subroutine, use the unary
prefix ** operator:
foo(**@onetothree); # array flattened before &foo called
</quote>
===
So is ** actually a seperately implemented operator, or is that the *
op working on the return from the * op, like the way Larry suggested
the ref-of-ref operator, \\ ? :)
__________________________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo
http://search.yahoo.com
I suspect that the return of * will be a lazy list (iterator?). So the
return of *(*(x)) would be another lazy list.
Since the description promises flattening before the subroutine call, I
interpret that as a "sequence point" -- that if I have an overloaded
object:
class LoudArray is Array {
method FLATTEN {
print "Help! Help! I'm being oppressed!\n";
return SUPER::FLATTEN;
}
}
sub cartman {
print "You will respect my authoritie!\n";
}
my @peasant is LoudArray = 1..5;
cartman(@peasant); # Mixing metaphors
it will (guaranteed) print its (Python-esque) message before any
(SouthPark-ian) reply.
==========
I'm imagining the differences invoke something like:
my @X = (1, 2, (3, 4, 5), 6, 7);
sub flatlander($a, $b, @c, *@d) {...}
flatlander(*@X);
flatlander(**@X);
In the two versions, I *think* you get (and I hope someone confirms or
corrects this):
*@X: $a = 1, $b = 2, @c = ((3, 4, 5), 6, 7), @d = ()
**@X: $a = 1, $b = 2, @c = (3, 4, 5), @d = (6, 7)
I believe that the lazy flattener would essentially behave like a regex
in greedy mode: "You're an array, and there's nothing after you to
positively require a value? Great, you take the rest!"
Kind of like:
rule flatlander_signature { <arg> <arg> (<arg>+) (<arg>*) }
While the pre-flattened version would just strip off one set of parens,
and only then try to bind the args. More like a non-greedy version, it
would minimize the amount consumed by @c.
=Austin
Er, that was a joke...
* and ** are identical insofar as they defeat signatures and impose list
context on the rest of the arguments in the list. The only difference
is that for ** there's an extra internal call to flatten() or some such
that un-lazifies anything lazy in the list.
Larry
I think * and ** should have identical semantics, apart for timing
differences.
Larry
yeah, I know. And I know ** was not. I was just wondering out loud
about how it would work in more detail, and phrased it horribly as
usual. :)
> * and ** are identical insofar as they defeat signatures and impose
> list context on the rest of the arguments in the list. The only
> difference is that for ** there's an extra internal call to flatten()
> or some such that un-lazifies anything lazy in the list.
> Larry
See? That makes me think that **@x is similar to *(*(@x)).
Similar, but still implemented seperately? Or is using the one
effectively like using the other aside from precedence twiddling with
the parens?
Either way, the important things to know:
- both flatten
- ** prevents laziness
Hmm, maybe I should put one of those on my shopping list next to the tuits....