Do slurpy parameters auto-flatten arrays?

9 views
Skip to first unread message

Ingo Blechschmidt

unread,
Jul 26, 2005, 4:52:41 PM7/26/05
to perl6-l...@perl.org
Hi,

are the following assumptions correct?

sub foo (*@args) { @args[0] }

say ~foo("a", "b", "c"); # "a"

my @array = <a b c d>;
say ~foo(@array); # "a b c d" (or "a"?)
say ~foo(@array, "z"); # "a b c d" (or "a"?)
say ~foo(*@array); # "a"
say ~foo(*(@array, "z")); # "a"

sub bar (*@args) { +@args }

say bar(1,2,3); # 3
say bar(@array); # 1 (or 4?)
say bar(@array, "z"); # 2 (or 5?)
say bar(*@array); # 4


--Ingo

--
Linux, the choice of a GNU | There are no answers, only
generation on a dual AMD | cross-references.
Athlon! |

Luke Palmer

unread,
Jul 27, 2005, 4:58:45 AM7/27/05
to Ingo Blechschmidt, perl6-l...@perl.org
On 7/26/05, Ingo Blechschmidt <ibl...@web.de> wrote:
> Hi,
>
> are the following assumptions correct?
>
> sub foo (*@args) { @args[0] }
>
> say ~foo("a", "b", "c"); # "a"

Yep.

> my @array = <a b c d>;
> say ~foo(@array); # "a b c d" (or "a"?)
> say ~foo(@array, "z"); # "a b c d" (or "a"?)

"a" for both of these. The *@ area behaves just like Perl 5's calling
conventions. I could argue for never auto flattening arrays, but then
there'd really be no difference between @ and $.

> say ~foo(*@array); # "a"
> say ~foo(*(@array, "z")); # "a"

Hmm, *(@array, "z")... what does that mean? Whatever it means, you're
correct in both of these. In the latter, the @array is in a
flattening context, so it gets, well, flattened.

> sub bar (*@args) { +@args }
>
> say bar(1,2,3); # 3
> say bar(@array); # 1 (or 4?)

4

> say bar(@array, "z"); # 2 (or 5?)

5

> say bar(*@array); # 4

Yep.

Luke

Piers Cawley

unread,
Aug 3, 2005, 5:32:19 AM8/3/05
to Luke Palmer, Ingo Blechschmidt, perl6-l...@perl.org
Luke Palmer <lrpa...@gmail.com> writes:

Wha? And I mean that sincerely. That's cockeyed. Surely a *@args in the
signature simply says 'gather up the rest of the args and stick 'em in this
list'. In this case @array is a single argument, so @args should be equal to
[@array]. If I'm calling the function and I want @array to be treated as
anything but a single argument I use *@array.

>> say bar(@array, "z"); # 2 (or 5?)
>
> 5

Double wha? That's even worse.

Do you claim that

say bar('z', @array)

also emits 5? Ick.


>> say bar(*@array); # 4
>
> Yep.

So how *do* I pass an unflattened array to a function with a slurpy parameter?

Aankhen

unread,
Aug 3, 2005, 9:28:34 AM8/3/05
to perl6-l...@perl.org
On 8/3/05, Piers Cawley <pdca...@bofh.org.uk> wrote:
> So how *do* I pass an unflattened array to a function with a slurpy parameter?

Good question. I would have thought that one of the major gains from
turning arrays and hashes into references in scalar context is the
ability to specify an unflattened array or a hash in a sub call
without any special syntax...

Aankhen

Luke Palmer

unread,
Aug 3, 2005, 1:28:11 PM8/3/05
to Aankhen, perl6-l...@perl.org

Well, you can, usually. This is particularly in the flattening
context. In most cases, for instance:

sub foo ($a, $b) { say $a }
my @a = (1,2,3);
foo(@a, "3");

Passes the array into $a. If nothing flattened by default, then you'd
have to say, for example:

map {...} *@a;

And even:

for *@a -> $x {...}

Which I'm not sure people want.

And the way you pass an array in slurpy context as a single reference
is to backwhack it. What it comes down to is that either you're
backwhacking things a lot or you're flattening things a lot. Perl
currently solves it by making the common case the default in each
"zone" of parameters.

I would be interested to hear arguments to the contrary, however.

Luke

Miroslav Silovic

unread,
Aug 3, 2005, 7:39:48 AM8/3/05
to pdca...@bofh.org.uk, lrpa...@gmail.com, ibl...@web.de, perl6-l...@perl.org
pdca...@bofh.org.uk wrote:

>So how *do* I pass an unflattened array to a function with a slurpy parameter?
>
>

I don't ~~ @larry, but my guess(es) would be bar(\@array) or bar([@array])

Miro

Piers Cawley

unread,
Aug 3, 2005, 5:52:08 PM8/3/05
to Luke Palmer, Aankhen, perl6-l...@perl.org
Luke Palmer <lrpa...@gmail.com> writes:

> On 8/3/05, Aankhen <aan...@gmail.com> wrote:
>> On 8/3/05, Piers Cawley <pdca...@bofh.org.uk> wrote:
>> > So how *do* I pass an unflattened array to a function with a slurpy parameter?
>>
>> Good question. I would have thought that one of the major gains from
>> turning arrays and hashes into references in scalar context is the
>> ability to specify an unflattened array or a hash in a sub call
>> without any special syntax...
>
> Well, you can, usually. This is particularly in the flattening
> context. In most cases, for instance:
>
> sub foo ($a, $b) { say $a }
> my @a = (1,2,3);
> foo(@a, "3");
>
> Passes the array into $a. If nothing flattened by default, then you'd
> have to say, for example:
>
> map {...} *@a;
>

I would assume that the way to implement map is:

multi sub map(&block, @array) { map &block, *@array }
multi sub map(&block, *@array) { ... }

If I call map like:

map {...} @a, @b, @c;

then I would expect the block to be called three times with @a, @b and @c as
the respective arguments.


I think the problem I have with this is that unless I missed something, the
default prototype for a block is *@_. If slurpiness works as described, then

$func = { +@_[0] }
$func.(@array)

doesn't return the length of the array, but the numification of its first element.

It seems to me that a slurpy parameter spec should simply say "Grab the
rest of the arguments and stick 'em in this array/hash", a function's caller
should control the flattening of a particular array argument, not the thing it
calls.

One of us has obviously misread the appropriate Apocalypse/Synopsis/Exegesis. I
have the horrible feeling that it's probably me, but I do think that the
interpretation I propose is the least surprising and most useful.

By the way, if flattening that way, what's the prototype for zip? We can after
all do:

zip @ary1, @ary2, @ary3, ... @aryn

Reply all
Reply to author
Forward
0 new messages