in reply to Re^6: Scalar context of slice ("list")
in thread Scalar context of slice

You ... make an argument about how you can claim that "grep doesn't really 'return a list'". ... But slices and grep are both examples where Perl ... will do exactly that: produce a list of scalar values (on the stack) despite that list being produced "in a scalar context".

Actually, it is the source that make that argument:

PP(pp_grepwhile) ... if (gimme == G_SCALAR) { // Scalar context dTARGET; XPUSHi(items); // Choose the scalar that gets returned. } else if (gimme == G_ARRAY) SP += items; RETURN; } ...
That is, there is, in fact, no general "just return the last item of the list" code in Perl.
c:\test>perl -MO=Concise -wle"print scalar( 1, 2, 3 );" Useless use of a constant in void context at -e line 1. 8 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 7 <@> print vK ->8 3 <0> pushmark s ->4 - <1> scalar sK/1 ->7 6 <@> list sK ->7 <<< And yet, there it is. 4 <0> pushmark v ->5 - <0> ex-const v ->- - <0> ex-const v ->5 5 <$> const[IV 3] s ->6 -e syntax OK

There are two important descriptions that can be applied to the affects produced by running a piece of code:

  1. There is the detailed, 100% accurate, blow-by-blow, nitty-gritty description of what actually happens.
  2. And there is the description of some abstraction (usually, one of many possible), that confines itself to describing those affects, whilst seeking to hide the details, as any good abstraction should.

Despite Perls' celebration of TIMTOWTDI, it has become derigour to only accept one abstract description of many of those affects. The problem is that the "one true abstract description", neither accurately describes the reality of what and how things happen, nor even provides a consistent abstraction to explain the easily observable affects. The results of these "one true way"-isms, is that we are left with no acceptable way to talk about things, that we write every day.

This ('a','b','c') is obviously, observably, more than one thing, because when we ask to print it:

c:\test>perl -wle"print for ( 'a','b','c' )" a b c

When we place that thing that consists of more than one thing, in what I hope no one will dispute is a "scalar context", it produces a different result:

c:\test>perl -wle"print for scalar(( 'a','b','c' ))" Useless use of a constant in void context at -e line 1. Useless use of a constant in void context at -e line 1. c

It (the thing) becomes; reduces to; produces; something different. A scalar value.

So, it's just a matter of agreeing a name or terminology that we can use decribe that thing: - A set of scalars? Too many connuctations. - A collection of scalars? Likewise. - A string of scalars? Not good. - A comma-separated sequence of scalar values? Possible, but what about the parens? They are important! Without them that comma-separated sequence behaves entirely differently:

c:\test>perl -wle"print for scalar 'a','b','c'" a b c c:\test>perl -wle"@a = (1,2,3); print for @a" 1 2 3 c:\test>perl -wle"@a = 1,2,3; print for @a" Useless use of a constant in void context at -e line 1. Useless use of a constant in void context at -e line 1. 1

So, whatever you term ( 'a','b','c' ), it is affected by context.

In a G_ARRAY context, it produces...um..itself really.

And in a G_SCALAR context it results in a scalar 'c'.

So, if ( 'a','b','c' ) is a 'list', then how do you describe putting that thing in a scalar context?

Surely it is clear that this fact has very little to do with what a slice (array slice, hash slice, or list slice) returns in a scalar context.

Now, I don't know about you, but this:

PP(pp_aslice) { dSP; dMARK; dORIGMARK; register AV* const av = (AV*)POPs; register const I32 lval = (PL_op->op_flags & OPf_MOD || LVRET); if (SvTYPE(av) == SVt_PVAV) { const I32 arybase = PL_curcop->cop_arybase; if (lval && PL_op->op_private & OPpLVAL_INTRO) { register SV **svp; I32 max = -1; for (svp = MARK + 1; svp <= SP; svp++) { const I32 elem = SvIVx(*svp); if (elem > max) max = elem; } if (max > AvMAX(av)) av_extend(av, max); } while (++MARK <= SP) { register SV **svp; I32 elem = SvIVx(*MARK); if (elem > 0) elem -= arybase; svp = av_fetch(av, elem, lval); if (lval) { if (!svp || *svp == &PL_sv_undef) DIE(aTHX_ PL_no_aelem, elem); if (PL_op->op_private & OPpLVAL_INTRO) save_aelem(av, elem, svp); } *MARK = svp ? *svp : &PL_sv_undef; } } if (GIMME != G_ARRAY) { MARK = ORIGMARK; *++MARK = SP > ORIGMARK ? *SP : &PL_sv_undef; SP = MARK; } RETURN; }

looks a lot like it pushes the sliced elements onto the MARKSTACK, (which is as good a definition of what a 'list' is in the full nitty-gritty description as I can think of), before deciding what the context is and then discarding all but the last element if it happens to be G_SCALAR.

So, if a list literal in the source, becomes a 'list' when it is pushed into the stack, doesn't it hold that when the multiple scalars produced by slicing an array is pushed onto the stack, it also becomes a list? And that all but the last element of that stack-held list of scalars are then discarded when in a scalar context?

Just as we say "I've boiled the kettle" not "I boiled the water in the kettle", with the subtle inaccuracy understood and glossed over. Or, "I flew to Rio" instead of "I boarded an airplane which flew to Rio".

Is it such a "bad meme" to say: A slice results in a list. And a list in a scalar context will return the last element of the slice? Rather than: an array slice constructor pushes the selected element of the array onto the markstack and if that array slice constructor is used within the confines of a scalar context then the stack pointer will be adjusted leaving just the last element accessible.

The oft-made observation that because of the scalar context, the comma operator reduces the thing (set of things, collection of things...) to a scalar before it ever became a list is both technically incorrect, and abstractly absurd.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

Replies are listed 'Best First'.
Re^8: Scalar context of slice ("list")
by ikegami (Patriarch) on Oct 04, 2008 at 09:20 UTC

    doesn't it hold that when the multiple scalars produced by slicing an array is pushed onto the stack, it also becomes a list? And that all but the last element of that stack-held list of scalars are then discarded when in a scalar context?

    So whether an op returns a list or not depends on whether it creates a list internally? It doesn't makes sense to describe the result of a function using different terminology based on whether it builds a list internally or not in order to return that result.

    For example, say grep built a list on the stack even in scalar context in an old version of Perl. According to what you said, that grep returns a list in scalar context. That means grep returns a list in scalar context in one version of Perl but not in others, despite returning the number of unfiltered elements in both.

    Is it such a "bad meme" to say: A slice results in a list. And a list in a scalar context will return the last element of the slice?

    Yes, cause it commonly fails. In the aforementioned version of grep, grep results in a list. And a list in scalar context will return... the last element of the grep? No, it didn't.

        Function of operators in question:

        • Slice in list context returns the specified elements.
        • Slice in scalar context returns the last of the specified element.
        • List assignment in list context returns its LHS.
        • List assignment in scalar context returns the number of elements assigned.
        • Scalar assignment in any context returns its LHS.

        Applying precedence and associativity, we get:

        1. Right-most slice (in list context) returns the specified elements.
        2. Left-most slice (in list context) returns the specified elements.
        3. List assignment (in scalar context) returns the number of elements assigned.
        4. Scalar assignment (in list context) returns its LHS.
Re^8: Scalar context of slice ("list")
by tye (Sage) on Oct 06, 2008 at 03:50 UTC
    You ... make an argument about how you can claim that "grep doesn't really 'return a list'". ... But slices and grep are both examples where Perl ... will do exactly that: produce a list of scalar values (on the stack) despite that list being produced "in a scalar context".
    Actually, it is the source that make that argument:

    Um, the second "..." above was "(at least some versions of Perl)" so showing source code for some other version of Perl isn't much of a counter argument. Exactly which versions of Perl was even noted elsewhere in this thread in reply to you.

    So are you arguing that grep used to return a list so it used to give the last item in scalar context? Or are you arguing that grep was designed to not return the last item because it was known that one day grep would be optimized to no longer "return a list"? Or are you going off on some tangent unrelated to my point, which is that it makes no sense to claim that a slice returns the "last item" because "a slice returns a list and a list ..."?

    That is, there is, in fact, no general "just return the last item of the list" code in Perl.
    6 <@> list sK ->7 <<< And yet, there it is.

    I'm not sure what you are talking about. I don't see where you show code that does the "take the last item of a list" for any construct that "returns a list", such as for the three different types of slice.

    If there were such code, then there would have been no need for me to patch one of those slice forms to add yet another copy of the code that takes the last item (and Perl wouldn't have dumped core).

    Despite Perls' celebration of TIMTOWTDI, it has become derigour to only accept one abstract description of many of those affects.

    Whatever. I'm not arguing for some "one true" abstraction. I've often argued for the opposite and several places in the node that you replied to I mention multiple ways of describing things. There doesn't have to be only "one true" abstaction for me to point out that "a slice returns a list therefore it ..." is a bizarre rationalization.

    So, if a list literal in the source, becomes a 'list' when it is pushed into the stack, doesn't it hold that when the multiple scalars produced by slicing an array is pushed onto the stack, it also becomes a list?

    Yes, they both (in recent versions of Perl) produce an intermediate list of scalar values on the stack (which is often called just "list" but is also certainly not the same thing as the "list literal" construct, as evidenced by your own sentence).

    And that all but the last element of that stack-held list of scalars are then discarded when in a scalar context?

    No, not in the least. The code that selects the last item of the list (of scalar values on the stack) for a list literal is completely separate from the three versions of that code that exist for the three types of slices (hash slices, array slices, and list slices)1. It is trivial to make a version of Perl where a hash slice in scalar context returns the number of items, an array slice in scalar context returns the first item, and a list slice in scalar context does something else. There are 4 different pieces of code representing four different design decisions (or, for most of those, more like "non-decisions", I expect, especially since I wrote one and made no design decision when doing so).

    1 See the bottom of pp_aslice(), the bottom of pp_hslice(), and the middle of pp_lslice() all (probably) in pp.c for 3 of those four separate checks against GIMME.

    Just as the code for grep (in older versions of Perl) that selects a count (after pushing a list onto the stack) was separate.

    If your argument made sense, then surely grep in Perl prior to 5.010 would also have to return the last item when in a scalar context.

    Just as we say "I've boiled the kettle" not "I boiled the water in the kettle", with the subtle inaccuracy understood and glossed over.

    I never objected to using simply "list" in places2. Now, if one tried to make a proclamation "I've boiled the kettle and driving while boiled is likely to make the coppers boiled, therefore if the kettle drives it will be a police officer" switching between three different meanings of "boiled" in the same sentence, few would be convinced.

    2 Now, it is best to make clear more precisely what you mean by "list" in that particular context. And it is important for readers of text about Perl to realize that "list" can mean quite a few different things. Without those two conditions, we get things like a SoPW node asking about writing [('a','b','c')] in a regex because the documentation says you put a "list of characters" between the brackets (true story, though I couldn't think of a likely strategy for finding it with a reasonable amount of time/effort, so I didn't look and it was many years ago so the details are surely imperfectly remembered).

    Similarly, it makes no sense to use two (or even three) different definitions of "list" in an argument "X is a 'list', a 'list' does Y, therefore X does Y".

    Is it such a "bad meme" to say: A slice results in a list. And a list in a scalar context will return the last element of the slice? Rather than: an array slice constructor pushes the selected element of the array onto the markstack and if that array slice constructor is used within the confines of a scalar context then the stack pointer will be adjusted leaving just the last element accessible.

    Strawman. I simply say "a slice in scalar context returns the last item". If somebody asks "why?", then I certainly don't say "because it is a list, not an array". Further, when I've seen other people claim that or hear it claimed, I've often also seen them later tripping over the misconceptions involved. Otherwise it would just be a semantic argument and not something I'd find worth wasting much time or effort on.

    And, yes, a simple but wrong explanation of "why?" is worse than a correct explanation of "why?" whether it is simpler or more complex. Simply "because that was the way Perl was built" is a reasonable answer. I've certainly never written the horrid explanation that you offered as the strawman alternative.

    The oft-made observation that because of the scalar context, the comma operator reduces the thing (set of things, collection of things...) to a scalar before it ever became a list is both technically incorrect, and abstractly absurd.

    I wrote above that "there is no such thing as 'a list in scalar context'" "is actually an incorrect statement". Though, I've never noticed it being "oft-made" regarding comma operators. Nor do I find it "abstractly absurd".

    - tye        

      I simply say "a slice in scalar context returns the last item".

      If you (and others) confined yourselves to "simply saying": It would be more accurate to say that 'a slice' rather than 'a list' in a scalar context returns the last item., then this exchange would probably never have taken place.

      Instead we get long, rambling, high-horse rants about how "there is no such thing as a list in a scalar context", when there patently is: print scalar(1,2,3);.

      Which inevitably leads to further long, rambling tirades about how there are many different meaning of the term 'list' in Perl.

      Using the term unqualified inevitably brings the language pedants crawling out of the woodwork to demonstrate their superior understanding, despite that most readers will:

      1. understand what the writer meant;
      2. intellectually gloss over any exceptional, technical inaccuracies that the unqualified use of the term might be subject to;
      3. understand that most of us neither want nor need to add a dozen levels of footnotes to our writings;
      4. nor want to bother trying to decipher the writings of those that do feel that need.

      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Instead we get long, rambling, high-horse rants about how "there is no such thing as a list in a scalar context", when there patently is: print scalar(1,2,3);.

        Since even that list doesn't return a list, would it be accurate to say "a list can't be returned in scalar context" (for when it happens, Perl core dumps)?