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."

In reply to Re^7: Scalar context of slice ("list") by BrowserUk
in thread Scalar context of slice by thenaz

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.