Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Re: Confused as to why the "casting context" is mis-behaving ("list vs array", again)

by tye (Cardinal)
on Oct 21, 2010 at 05:24 UTC ( #866470=note: print w/ replies, xml ) Need Help??


in reply to Confused as to why the "casting context" is mis-behaving

Ah, lots of constructing of the false dichotomy of "list" vs "array". "It returns/is a list and therefore returns its last item in scalar context" is utter nonsense, though quite persistent nonsense in part because it gives the "right answer" in several cases. Also because "list" is very often used to mean "list literal" (use of the comma operator) and is also very often used to talk about what is returned by lots of different things, including slices.

So, yes, a list literal gives its last item in scalar context (be careful how you define "item", though). Yes, a slice returns a list of scalar values. Yes, lots of things that return a list of scalar values also return the last item when in scalar context. Yes, slices do that.

But, no, a list of scalar values is not a list literal (a list literal does return a list of scalar values when used in a list context). No, a slice does not return a list literal; a list literal is a syntax construct and thus is not something that can be "returned". No, not all things that return a list of scalar values give the last item when in scalar context. No, a slice is not just syntactic sugar for a list literal.

And, no, the last time I checked, what a slice returns in scalar context is not even documented. Nor was it designed. It came to be as a quick patch to fix a core dump and no documentation change accompanied it.

Yes, grep and map both return lists of scalar values. Yes, they both return the number of elements when in a scalar context. By the logic of the "is it a list or an array?" meme, clearly grep and map must return arrays. No, they don't return arrays (for example, you can push to an array). You can't even return an array in Perl (you can return a reference to an array and you can write "return @array;" but that returns (a copy of) the list of scalar values that are in the array).

The reality is that each operation type in Perl that can return a list (of scalar values) also has a specific thing it will return when in a scalar context. Almost all of those cases are documented. The majority of cases return the last item. Several return a count. Several return the first item. Even more do something else.

Slices return the last item because that is the easiest thing to do in a quick patch (you just reduce the stack size to 1) and that quick patch got accepted. Period.

(Update) On Scalar Context lists many of the cases.

- tye        


Comment on Re: Confused as to why the "casting context" is mis-behaving ("list vs array", again)
Download Code
Re^2: Confused as to why the "casting context" is mis-behaving ("list vs array", again)
by andal (Friar) on Oct 21, 2010 at 08:04 UTC
    You can't even return an array in Perl (you can return a reference to an array and you can write "return @array;" but that returns (a copy of) the list of scalar values that are in the array).

    This is not 100% correct. The array is returned from the function. But to get a hold of it, you should COPY it somewhere. Either in another array, or into list of variables. Or where ever.

    perl -e 'sub test{my @a=qw(a b c); return @a} my $v = test(); print $v +,"\n"' perl -e 'sub test{return qw(a b c);} my $v = test(); print $v,"\n"' perl -e 'sub test{my @a=qw(a b c); return @a} my ($a, $v) = test(); pr +int $v,"\n"' perl -e 'sub test{my @a=qw(a b c); return (@a)} my $v = test(); print +$v,"\n"' perl -e 'sub test{my @a=qw(a b c); return (@a, "b")} my $v = test(); p +rint $v,"\n"'

    Everything in perl becomes logical if you think about @abc as about OBJECT, and about list as COLLECTION of objects. So obtaining a slice from the array gives you collection of objects. grep or map work with collections of objects, so if you pass array to them, this array is turned into collection of objects. Of course, neither grep nor map can return array since they have only collection of objects as input.

    Placing array as member into collection/list does not make this array disappear. It stays in the list as the object. But when the list is copied somewhere, then the array object might be replaced with its elements. Depends on the context.

      This is not 100% correct. The array is returned from the function. But to get a hold of it, you should COPY it somewhere.

      No, the array is copied before the function returns. You can observe that:

      my @a= ( 'a' .. 'e' ); sub returnArray { return @a; } my @b= ( 'v' .. 'z' ); for( returnArray() ) { $_ .= '?' } for( @b ) { $_ .= '!' } print "@a\n"; print "@b\n"; __END__ a b c d e v! w! x! y! z!

      And it is also not true that the function returns and then (after that) the scalar context decides to get the size of the array while the list context decides to copy the elements of the array.

      The context gets passed in to the function, to the returning statement so that it can, when possible, avoid the work of creating a whole list of values just to throw that list away.

      The method of returning information from a Perl function is to push zero or more scalar values onto the stack. return @array;, if called in a list context, loops over the array and pushes onto the stack, a copy of each element of the array. If you assign the return value to an array, then that assignment operator loops over the items on the stack and puts them into the array (whether each value is copied again here or the array just gets aliases to each of the original copies is an implementation detail and a matter of optimization that I have never needed to worry about).

      - tye        

        No, the array is copied before the function returns. You can observe that:

        You missed the point. It does not make any difference when the array is copied, before or after the return. The point was, when the function returns, the caller "can know" that some array was returned. So it makes difference what you return from the function, array or list or scalar.

        If you just wanted to say, that the array seen by the caller is not the same object as the array that was given to "return", then you are absolutely correct. But this is true for any returned object. Even references to arrays are copied, they are not the same references as the returned variables. Of course they reference the same array, but they are not the same references. So arrays are not an exception to this rule. It is general feature of the language.

        By the way, your code examples don't prove that the copying happens before the return. They just prove, that the "for" loop works with copies of values. Nothing else. When those copies were made stays unclear :)

Overcoming the nonsense
by ig (Vicar) on Oct 21, 2010 at 08:10 UTC

    I think the absence of documentation you note is the root of the persistence of the nonsense. In the absence of information in common references, many people are inclined to make up answers to their questions based on the little they know.

    I wonder what your thoughts are about the prospect of getting perldata, perlfunc, perlsyn and perlop updated to provide less nonsensical descriptions of what the data structures, operators, functions and behaviors actually are, to cover the current omissions, so that people are less inclined to make up nonsense.

      patches are always welcome :)

        Yes. I have submitted a few (very few) which have been well received. Last I noticed, I think I was credited with something like 0.0008% of all of perl (or maybe that was just of the recent changes to perl) - which pleased me out of all proportion to the smallness of the number. I have started on some patches to doc:/perldata and perlop covering what has been discussed here (and elsewhere) and will submit them if I get to the point I think they are worthy.

Re^2: Confused as to why the "casting context" is mis-behaving (docs)
by moritz (Cardinal) on Oct 21, 2010 at 11:17 UTC
    And, no, the last time I checked, what a slice returns in scalar context is not even documented.

    now changed in blead perl

    Perl 6 - links to (nearly) everything that is Perl 6.
      Patch is wrong. $u is assigned '2'

      ...which appears to have been fixed already. It would have been clearer had the data been adjusted instead of the comment.

        Patch is wrong.

        Right.

        $u is assigned '2'

        No, 'B'. Which is why it's clearer to change the comment, not the data.

        Perl 6 - links to (nearly) everything that is Perl 6.
Re^2: Confused as to why the "casting context" is mis-behaving ("list vs array", again)
by philipbailey (Chaplain) on Oct 21, 2010 at 11:52 UTC

    The dichotomy is false, for the reasons that you give, but I would argue that is by no means "nonsense". As a simplification, a model, for the behaviour of Perl, the list vs. array distinction remains useful. It is better to have a model, with exceptions, than no model at all.

      The reason I point out the nonsense of it is because I repeatedly see people make mistakes based on the model. I don't think having an incorrect model that leads to the right answer for the wrong reasons in a few cases but also leads to a fundamental misunderstanding and also leads to the wrong answer in a lot of other cases is better than having a better model.

      The alternative is not "no model at all". The alternative is actually a simple model that matches reality much better.

      - tye        

        So what is the "simple model that matches reality"? I guess what you are saying is "it depends, look at the documentation" for each case. Correct me if you are saying something different.

        The difficulty with saying to newer users of Perl that everything is a documented special case is that (1) it is hard to remember all those special cases, and (2) not everything is documented adequately. It's useful to have some default model to explain common behaviour.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (5)
As of 2014-12-29 11:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (187 votes), past polls