Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Re^5: Confused as to why the "casting context" is mis-behaving

by ig (Vicar)
on Oct 21, 2010 at 17:54 UTC ( #866604=note: print w/ replies, xml ) Need Help??


in reply to Re^4: Confused as to why the "casting context" is mis-behaving
in thread Confused as to why the "casting context" is mis-behaving

But I do find it interesting, as I said.

In fact, that example led me to a much more correct understanding of what is happening. I wasn't aware of it and would never have looked for such insight into how literal lists behave in perltrap, so thank you for pointing it out.

I agree that what you found in perltrap should be presented elsewhere. I had said Context but on further consideration I think List value constructors would be a better place. There is already an example with a scalar variable as the last "value" (using the terminology in List value constructors, though I wonder if that is the best terminology) in the literal list. I think the example from perltrap would be a fine addition to that section.

I do think there are faults in the example in perltrap. I get the same result described with the version of perl5 I have tested with. I don't have any perl4 handy to test that prior behavior with.

The description in perltrap is inconsistent with perl 5.10.0 that I have recently been testing with. The description says:

The comma operator in a scalar context is now guaranteed to give scalar context to its arguments.

Consider:

print "Scalar assignment:\n"; $x = ( context(1), context(2), context(3) ); print "\$x = $x\n\n"; print "List assignment:\n"; @x = ( context(1), context(2), context(3) ); print "\@x = @x\n"; sub context { my $arg = shift; if(wantarray) { print "$arg: list context\n"; return("oranges", "lemons"); } elsif(defined(wantarray)) { print "$arg: scalar context\n"; return("apples"); } else { print "$arg: void context\n"; return("into the..."); } }

Which produces:

Scalar assignment: 1: void context 2: void context 3: scalar context $x = apples List assignment: 1: list context 2: list context 3: list context @x = oranges lemons oranges lemons oranges lemons

So, the example says the comma operator is guaranteed to give scalar context to its arguments when evaluated in scalar context, but in perl 5.10.0 I see void context in some cases.

This raises yet another issue: what does the comma operator (or any operator) do in void context?

perlop says the comma operator is left associative. I take this to mean that ( 1, 2, 3 ) is the same as ( ( 1, 2 ), 3 ) rather than ( 1, ( 2, 3 ) ). If I am correct, one description of the comma operator that is consistent with my observations would be:

In scalar context, the comma operator evaluates its left argument in void context and discards any result then evaluates its right argument in scalar context and returns the resulting scalar.

In void context, the comma operator evaluates both its arguments in void context and returns nothing.

But, I haven't looked at the internals of perl, and this may be more of the nonsense that so frustrates tye.

While tye said the comment at the end of the example you quote is misleading, I would go further and say it is wrong. It should say (IMHO) "Knows scalar uses length of array", as tye said. The ambiguity is, I think, in which "list" is referred to in the last comment in the example. The comment is correct if one considers it to refer to the list of values in the array @y, but incorrect if one considers it to refer to the literal list ending with @y.

More than reporting bugs, most people will continue to produce nonsense descriptions and explanations if this isn't better documented. This will lead to many surprises, which Perl/perl is supposed to avoid. In this case, I think better documentation is the most pragmatic means to reducing the element of surprise.


Comment on Re^5: Confused as to why the "casting context" is mis-behaving
Select or Download Code
Re^6: Confused as to why the "casting context" is mis-behaving (void,void,scalar)
by tye (Cardinal) on Oct 22, 2010 at 18:21 UTC

    The "scalar context" guarantee that the perltrap item is talking about is only for the last expression of the list literal. Yes, not clear as worded.

    I don't look at Perl internals much. I care a lot more about observable behavior. I mostly just have a lot of experience (mostly at PerlMonks) of watching people hit edge cases.

    Here's a recent edge case:

    print "Scalar assignment:\n"; $x = ( context(1), context(2), context(3) ); print "\$x = $x\n\n"; print "List assignment:\n"; @x = ( context(1), context(2), context(3) ); print "\@x = @x\n\n"; sub list { ( context(1), context(2), context(3) ) } print "Scalar assignment in sub:\n"; $x = list(); print "\$x = $x\n\n"; print "List assignment in sub:\n"; @x = list(); print "\@x = @x\n\n"; sub context { my $arg = shift; if(wantarray) { print "$arg: list context\n"; return("oranges", "lemons"); } elsif(defined(wantarray)) { print "$arg: scalar context\n"; return("apples"); } else { print "$arg: void context\n"; return("into the..."); } } __END__ Scalar assignment: 1: void context 2: void context 3: scalar context $x = apples List assignment: 1: list context 2: list context 3: list context @x = oranges lemons oranges lemons oranges lemons Scalar assignment in sub: 1: scalar context # shouldn't this be void context? 2: scalar context # shouldn't this be void context? 3: scalar context $x = apples List assignment in sub: 1: list context 2: list context 3: list context @x = oranges lemons oranges lemons oranges lemons

    I briefly believed the reason for the scalar (not void) context for the commented lines so that you don't get warnings from:

    use warnings; sub list { ('a','b','c') } my @all= list(); my $last= list(); # Doesn't produce a warning

    - tye        

      I believe the reason for the scalar (not void) context for the commented lines so that you don't get warnings from:

      I've always thought it was that the compiler can't perform static analysis across function calls. (By the time of assigning return values, does the compiler know that any element of the stack was a literal?)

        I've always thought it was that the compiler can't perform static analysis across function calls.

        That would be a reason for the warning to not happen (and a reasonable one). It is not a reason for the context to be scalar rather than void.

        But, yes, I tried to remember what was discussed when this inconsistency was brought up and threw in a half-remembered guess at the last minute. It turns out to be incorrect. The "useless use of constant in void context" doesn't happen for the return value of a sub, even when the sub is called in a void context.

        I don't recall specific enough details about the last time this came up to have found a prior discussion of it. But I eventually stumbled upon ysth providing a much better explanation of this exception, Re: If you believe in Lists in Scalar Context, Clap your Hands (which I don't believe is even the discussion I was remembering).

        - tye        

      Scalar assignment in sub: 1: scalar context # shouldn't this be void context? 2: scalar context # shouldn't this be void context? 3: scalar context $x = apples

      It should be void, but it can't due to the way context is determined where it can vary at run-time. Known bug, but it can't readily be fixed.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://866604]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2014-10-22 08:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (114 votes), past polls