On Thu, Mar 25, 2004 at 08:42:53AM -0700, Luke Palmer wrote:
: Aaron Sherman writes:
: > More to the point is there ever a reason to want any array ref in list
: > context to NOT explode other than []? I can't think of any.
: > 
: >     push @a, $b
: > 
: > Is it too non-obvious that if $b is an array ref, then this is going to
: > extend @a by $b.length elements?
: 
: Quite a bit too subtle, yes.  While array references are now doing many
: of the same things in similar contexts as arrays, flattening in list
: context is not one of them.  Array references are still different beasts
: from arrays.  Your push example is one of the reasons why.

Yes, things that look like scalars have to stay scalars in list context.

: Some time back, Larry said that you had to do:
: 
:     push @a, @$b;
: 
: Just like in Perl 5.  But this was before * was a unary operator instead
: of a context forcing operator.  That is, as of A6:
: 
:     sub foo(@a, @b, @c, @d, @e);
:     foo(@a, @b, [EMAIL PROTECTED], @d);  # Flatten @c and @d into the parameter list
: 
: But now, it's:
: 
:     foo(@a, @b, [EMAIL PROTECTED], @d);  # Flatten @c into the parameter list
: 
: So that might mean that push looks like:
: 
:     push @a, *$b;

Yes, * was originally a no-op in list context, but I think now we can
use it to deref a list that would otherwise not interpolate itself.
It maps better onto how a C programmer thinks, and if in scalar
context it also happens to defer the signature checking to use the
interpolated values, that's just an extra bonus.

However, we'll have to be a little careful about calling it a
"flattening" operator, because it isn't exactly...  Normal list context
only flattens notionally in Perl 6, and the actual flattening is done
lazily by default.  If you really, truly want it flattened Right Now,
you have to use unary ** instead (by analogy to the ** prefix in the
declaration, or is it the other way around now?).  But usually you
want the * semantics such that, if a lazy list is interpolated into
the list, it's just another generator in that list.  To wit:

    $foo = 0...;        # take ref to an infinite range
    @bar = $foo;        # puts in the iterator as a reference
      say @bar.elems;   #  prints 1
    @bar = *$foo;       # puts in 0...
      say @bar.elems;   #  prints Inf
    @bar = **$foo;      # throws exception: "Please install a lot more memory"

It seems to be a useful mnemonic that, loosely speaking, ** is always
an "exponential" operator, one way or another...  :-)

Larry

Reply via email to