List context versus list context

B

Bo Lindbergh

Consider this snippet:
{
sub foo {
print scalar(@_)," arguments\n";
}

foo((17)[2,1]);
foo(my @foo=(17)[2,1]);
}

When run by my perl 5.8.8, it produces these two lines of output:
2 arguments
0 arguments

So there seems to be (at least) two kinds of list context,
one used for evaluating function arguments and another one used
for evaluating the rhs of an assignment. I can't find any mention
of this in perldata.pod. What's up?


/Bo Lindbergh
 
C

Ch Lamprecht

Bo said:
Consider this snippet:
{
sub foo {
print scalar(@_)," arguments\n";
}

foo((17)[2,1]);
this calls foo with two parameters
foo(my @foo=(17)[2,1]);

this assigns a slice containing an emty list to @foo and calls foo() with that.


try this, to see the difference:
foo(my @foo=(17,3,6)[2,1]);
}

When run by my perl 5.8.8, it produces these two lines of output:
2 arguments
0 arguments

So there seems to be (at least) two kinds of list context,
one used for evaluating function arguments and another one used
for evaluating the rhs of an assignment. I can't find any mention
of this in perldata.pod. What's up?


/Bo Lindbergh

Christoph
 
C

Ch Lamprecht

Ch said:
Bo said:
Consider this snippet:
{
sub foo {
print scalar(@_)," arguments\n";
}

foo((17)[2,1]);

this calls foo with two parameters
foo(my @foo=(17)[2,1]);


this assigns a slice containing an emty list to @foo and calls foo()
with that.


try this, to see the difference:
foo(my @foo=(17,3,6)[2,1]);
}

When run by my perl 5.8.8, it produces these two lines of output:
2 arguments
0 arguments

So there seems to be (at least) two kinds of list context,
one used for evaluating function arguments and another one used
for evaluating the rhs of an assignment. I can't find any mention
of this in perldata.pod. What's up?


/Bo Lindbergh


Christoph

sorry, I missed your point ;(

Christoph
 
T

Tad McClellan

Bo Lindbergh said:
Consider this snippet:
{
sub foo {
print scalar(@_)," arguments\n";
}

foo((17)[2,1]);
foo(my @foo=(17)[2,1]);
}

When run by my perl 5.8.8, it produces these two lines of output:
2 arguments
0 arguments

So there seems to be (at least) two kinds of list context,
one used for evaluating function arguments and another one used
for evaluating the rhs of an assignment.


It isn't really a context issue. It is a slice issue.

Slices are special-cased for list assignment.

I can't find any mention
of this in perldata.pod.


@c = (0,1)[2,3]; # @c has no elements
...
This makes it easy to write loops that terminate when a null list
is returned
...
 
X

xhoster

Tad McClellan said:
Bo Lindbergh said:
Consider this snippet:
{
sub foo {
print scalar(@_)," arguments\n";
}

foo((17)[2,1]);
foo(my @foo=(17)[2,1]);
}

When run by my perl 5.8.8, it produces these two lines of output:
2 arguments
0 arguments
So there seems to be (at least) two kinds of list context,
one used for evaluating function arguments and another one used
for evaluating the rhs of an assignment.

It isn't really a context issue. It is a slice issue.

Slices are special-cased for list assignment.
I can't find any mention
of this in perldata.pod.

@c = (0,1)[2,3]; # @c has no elements
...
This makes it easy to write loops that terminate when a null list
is returned
...

I don't quite get the documentation. It says:

A slice of an empty list is still an empty list. Thus:

@a = ()[1,0]; # @a has no elements
@b = (@a)[0,1]; # @b has no elements
@c = (0,1)[2,3]; # @c has no elements

But the third example is not the slice of an empty list! So while
an example is provided, that example doesn't match the description it
is supposedly an example of.

It seems that this would be more accurate:

A slice of an empty list is still an empty list. Thus:

@a = ()[1,0]; # @a has no elements
@b = (@a)[0,1]; # @b has no elements

Also, a slice completely after the end of a non-empty list is
an empty list. Thus:

@c = (0,1)[2,3]; # @c has no elements


Xho
 
T

Tad McClellan

Tad McClellan said:
It isn't really a context issue. It is a slice issue.

Slices are special-cased for list assignment.

I don't quite get the documentation. It says:

A slice of an empty list is still an empty list. Thus:

@a = ()[1,0]; # @a has no elements
@b = (@a)[0,1]; # @b has no elements
@c = (0,1)[2,3]; # @c has no elements

But the third example is not the slice of an empty list!


I was annoyed by that too.

So while
an example is provided, that example doesn't match the description it
is supposedly an example of.

It seems that this would be more accurate:

A slice of an empty list is still an empty list. Thus:

@a = ()[1,0]; # @a has no elements
@b = (@a)[0,1]; # @b has no elements

Also, a slice completely after the end of a non-empty list is
an empty list. Thus:

@c = (0,1)[2,3]; # @c has no elements


Looks like a docs patch to me...
 
C

Ch Lamprecht

Tad said:
Bo Lindbergh said:
Consider this snippet:
{
sub foo {
print scalar(@_)," arguments\n";
}

foo((17)[2,1]);
foo(my @foo=(17)[2,1]);
}

When run by my perl 5.8.8, it produces these two lines of output:
2 arguments
0 arguments


So there seems to be (at least) two kinds of list context,
one used for evaluating function arguments and another one used
for evaluating the rhs of an assignment.



It isn't really a context issue. It is a slice issue.

Slices are special-cased for list assignment.


I can't find any mention
of this in perldata.pod.



@c = (0,1)[2,3]; # @c has no elements
...
This makes it easy to write loops that terminate when a null list
is returned
...
I thought the context question was, why in this case
foo((17)[2,1]);
the expression (17)[2,1] evaluates to (undef,undef) ??

Maybe it has something to do with aliasing of function arguments...

Christoph
 
X

xhoster

Ch Lamprecht said:
Tad said:
Bo Lindbergh said:
Consider this snippet:
{
sub foo {
print scalar(@_)," arguments\n";
}

foo((17)[2,1]);
foo(my @foo=(17)[2,1]);
}

When run by my perl 5.8.8, it produces these two lines of output:
2 arguments
0 arguments


So there seems to be (at least) two kinds of list context,
one used for evaluating function arguments and another one used
for evaluating the rhs of an assignment.



It isn't really a context issue. It is a slice issue.

Slices are special-cased for list assignment.


I can't find any mention
of this in perldata.pod.



@c = (0,1)[2,3]; # @c has no elements
...
This makes it easy to write loops that terminate when a null list
is returned
...
I thought the context question was, why in this case
foo((17)[2,1]);
the expression (17)[2,1] evaluates to (undef,undef) ??

Maybe it has something to do with aliasing of function arguments...

It is starting to look like a bug.

A slice of an empty list is an empty list in both assignment and sub-arg.

A slice off the end of a nonempty list is an empty list in an assignment,
but not as the arg to a sub.

perl -e 'use Data::Dumper; sub foo {return @_}; \
print Dumper [foo(()[4..6])]'
$VAR1 = [];
perl -e 'use Data::Dumper; sub foo {return @_}; \
print Dumper [(()[4..6])]'
$VAR1 = [];
perl -e 'use Data::Dumper; sub foo {return @_}; \
print Dumper [((1)[4..6])]'
$VAR1 = [];
perl -e 'use Data::Dumper; sub foo {return @_}; \
print Dumper [foo((1)[4..6])]'
$VAR1 = [
undef,
undef,
undef
];


Xho
 
T

Tad McClellan

Ch Lamprecht said:
Tad said:
Bo Lindbergh said:
Consider this snippet:
{
sub foo {
print scalar(@_)," arguments\n";
}

foo((17)[2,1]);
foo(my @foo=(17)[2,1]);
}

When run by my perl 5.8.8, it produces these two lines of output:
2 arguments
0 arguments


[snip my explanation of why you get the "0 arguments" output]

I thought the context question was, why in this case
foo((17)[2,1]);
the expression (17)[2,1] evaluates to (undef,undef) ??


Ah ha.

The OP didn't say which of the two he understood and I ended up
picking the wrong one.

The real question here is why we're getting the "2 arguments" output.

Maybe it has something to do with aliasing of function arguments...


I believe you are onto something there, since the only place I
can get "2" is with the 4 things (are there more?) that do aliasing:
map, grep, foreach and sub arguments.


perl -le 'push @a, map $_, (17)[2,1]; print scalar @a'

perl -le 'push @a, grep 1, (17)[2,1]; print scalar @a'

perl -le 'foreach ( (17)[2,1] ) {push @a, $_} print scalar @a'

perl -le 'push @a, sub {return @_}->( (17)[2,1] ); print scalar @a'
 
B

Bo Lindbergh

Tad McClellan said:
I believe you are onto something there, since the only place I
can get "2" is with the 4 things (are there more?) that do aliasing:
map, grep, foreach and sub arguments.

sort does aliasing too, but you get 0 elements in that context:
{
my @a = sort { $b<=>$a; } ((17)[2,1]);
print scalar @a," elements\n";
# outputs "0 elements"
}

Wrapping the slice in a do-block gives you 0 elements
and still allows aliasing:
{
my($x,$y,@a)=(10,20);

foreach ( do { ((17)[2,1], $x, $y); } ) {
push(@a,$_++);
}
print scalar(@a)," elements, x=$x, y=$y\n";
# outputs "2 elements, x=11, y=21"
}

I'm afraid that any complete description of this is going to sound
badly incoherent.


/Bo Lindbergh
 
C

Charles DeRykus

...

It is starting to look like a bug.
...

A slice off the end of a nonempty list is an empty list in an assignment,
but not as the arg to a sub.

The "off-the-end" semantics in the 2 assignment examples below looks
unexpected to me too.

I can see that the 2nd example becomes a non-empty list but why should
it generate the additional undef's while the 1st example remains mired
in its own emptiness...:)



$ perl -MData::Dumper -le 'my @x = (0)[2,4,6]; print Dumper \@x'
$VAR1 = [];

$ perl -MData::Dumper -le 'my @x = (0)[0, 2,4,6];print Dumper \@x'
$VAR1 = [
0,
undef,
undef,
undef
];
 
T

Tad McClellan

Charles DeRykus said:
The "off-the-end" semantics in the 2 assignment examples below looks
unexpected to me too.

I can see that the 2nd example becomes a non-empty list but why should
it generate the additional undef's


It doesn't generate any "additional" undefs, 4 indexes, 4 values.

while the 1st example remains mired
in its own emptiness...:)


Because when it is _all_ undefs (ie. _all_ of the indexes are off
the end), the special case of returning an empty list kicks in.

perldata says

This makes it easy to write loops that terminate when a null list
is returned

as a "justification" for this behavior.

$ perl -MData::Dumper -le 'my @x = (0)[2,4,6]; print Dumper \@x'
$VAR1 = [];

$ perl -MData::Dumper -le 'my @x = (0)[0, 2,4,6];print Dumper \@x'
$VAR1 = [
0,
undef,
undef,
undef
];


Neither of these display the bug that is under discussion.

The 1st one generates the empty list rather than the non-empty list
that the bug gives.

The 2nd one is not _all_ off of the end, so a non-empty list is expected.

The bug is when all of the indexes are off the end and it returns
a non-empty list.
 
C

Charles DeRykus

Tad said:
It doesn't generate any "additional" undefs, 4 indexes, 4 values.




Because when it is _all_ undefs (ie. _all_ of the indexes are off
the end), the special case of returning an empty list kicks in.

perldata says

This makes it easy to write loops that terminate when a null list
is returned

as a "justification" for this behavior.

Thanks, I read that earlier and it went in one ear and breezed straight
through..
$ perl -MData::Dumper -le 'my @x = (0)[2,4,6]; print Dumper \@x'
$VAR1 = [];

$ perl -MData::Dumper -le 'my @x = (0)[0, 2,4,6];print Dumper \@x'
$VAR1 = [
0,
undef,
undef,
undef
];


Neither of these display the bug that is under discussion.

The 1st one generates the empty list rather than the non-empty list
that the bug gives.

The 2nd one is not _all_ off of the end, so a non-empty list is expected.

The bug is when all of the indexes are off the end and it returns
a non-empty list.

Got it now. The bug seems to manifest only as an argument call rather
than a direct assignment.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top