Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

* vs **

9 views
Skip to first unread message

Paul

unread,
Apr 22, 2003, 5:51:46 PM4/22/03
to perl6-l...@perl.org
S6:
===
<quote>
The unary prefix operator * flattens its operand (which allows the
elements of an array to be used as an argument list). The * operator
also causes its operand -- and any subsequent arguments in the argument
list -- to be evaluated in list context.

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

Austin Hastings

unread,
Apr 22, 2003, 6:22:58 PM4/22/03
to Hod...@writeme.com, perl6-l...@perl.org

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

Larry Wall

unread,
Apr 22, 2003, 10:24:17 PM4/22/03
to perl6-l...@perl.org
On Tue, Apr 22, 2003 at 02:51:46PM -0700, Paul wrote:
: S6:

: ===
: <quote>
: The unary prefix operator * flattens its operand (which allows the
: elements of an array to be used as an argument list). The * operator
: also causes its operand -- and any subsequent arguments in the argument
: list -- to be evaluated in list context.
:
: 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, \\ ? :)

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

Larry Wall

unread,
Apr 22, 2003, 10:25:51 PM4/22/03
to perl6-l...@perl.org
On Tue, Apr 22, 2003 at 03:22:58PM -0700, Austin Hastings wrote:
: 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.

I think * and ** should have identical semantics, apart for timing
differences.

Larry

Austin Hastings

unread,
Apr 22, 2003, 10:33:11 PM4/22/03
to Larry Wall, perl6-l...@perl.org

>From: Larry Wall [mailto:la...@wall.org]

Okay. Can you give us an illustrative case?

=Austin

Paul

unread,
Apr 23, 2003, 9:47:05 AM4/23/03
to Larry Wall, perl6-l...@perl.org

--- Larry Wall <la...@wall.org> wrote:
> On Tue, Apr 22, 2003 at 02:51:46PM -0700, Paul wrote:
> : S6:
> : ===
> : <quote>
> : The unary prefix operator * flattens its operand (which allows
> : the elements of an array to be used as an argument list). The *
> : operator also causes its operand -- and any subsequent arguments
> : in the argument list -- to be evaluated in list context.
> :
> : 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 3 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, \\ ? :)
>
> Er, that was a joke...

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....

0 new messages