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! |
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
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?
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
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
>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
> 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