Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re: If you believe in Lists in Scalar Context, Clap your Hands

by ikegami (Patriarch)
on Oct 23, 2008 at 22:55 UTC ( [id://719187]=note: print w/replies, xml ) Need Help??


in reply to If you believe in Lists in Scalar Context, Clap your Hands

First, some corrections:

$r = 'a'..'z' ; # Case 4 -- error

Maybe, but $r = 5..7; wouldn't be.

$r = (@r, @r) ; $v = (%r, %r) ;

the @r and %r are evaluated in Scalar Context

No, they're not.

use strict; use warnings; sub print_context { my $c = ( wantarray() ? 'List' : ( defined(wantarray()) ? 'Scalar' : 'Void' ) ); print("$c\n"); } my $r1 = ( print_context(), print_context() ); # Void # Scalar

However, they would be evaluated in scalar context in the following similar code:

my $r2 = sub { ( print_context(), print_context() ) }->(); # Scalar # Scalar

Now, some questions for you:

in List Context there are a number of things which make lists, including:

  • the empty list
  • singleton values (including undef)
  • literal lists -- two or more values separated by ',', grouped together by '()' if required
  • the '..' range operator
  • slicing other lists, arrays or hashes

How come array slices and hash slices are in that list, but not arrays and hashes?

Why aren't any named operators (such as grep and map) in that list?

what's wrong with the notion of a List in Scalar Context ?

Given that an array returns a list in list context, how do you place that list in scalar context?


Finally, an answer to your question:

BTW: I'm gagging to know how to describe why this:

$r = () = 1..27 ;

A list assignment ("() = 1..27") in scalar context ("$r =") evaluates to the number of elements to assign.

Finally, and for extra points (and points mean prizes), how does one describe the difference between a list and an array ?

An array is variable.
A list is a piece of code that generates a list operator.
A list is the operator generated from a list in the code.
A list is the result of an operator or function in list context.

Replies are listed 'Best First'.
Re^2: If you believe in Lists in Scalar Context, Clap your Hands
by gone2015 (Deacon) on Oct 24, 2008 at 01:43 UTC

    The difference you point out between:

    my $r1 = ( print_context(), print_context() ); # Void # Scalar my $r2 = sub { ( print_context(), print_context() ) }->(); # Scalar # Scalar
    is amusing -- not quite as consistent as I thought.

    Now, some questions for you:
    in List Context there are a number of things which make lists, including:
    ....

    How come array slices and hash slices are in that list, but not arrays and hashes?

    Why aren't any named operators (such as grep and map) in that list?

    OK. The list was things that make lists, which are the problematic things Scalar/List context-wise. At that point I was summarising what had been discussed so far... I went on to subroutines and named operators. Sorry if that was less than clear.

    what's wrong with the notion of a List in Scalar Context ?
    Given that an array returns a list in list context, how do you place that list in scalar context?

    I would argue that, when treated as an rvalue, this is the key difference between a list and an array. Since in Scalar Context the value of the array isn't the list, the case does not arise.

    I understand that it can also be argued that in Scalar Context there are no lists... however much it looks as though there might be.

    That the value of @array depends on the Context is one thing to understand. That ($a, $b, $c) or @z[@p] are or are not lists, depending on the Context, seems to me to be harder to get to grips with, and unnecessary.

    Finally, an answer to your question:
    BTW: I'm gagging to know how to describe why this:
    $r = () = 1..27 ;
    A list assignment ("() = 1..27") in scalar context ("$r =") evaluates to the number of elements to assign.

    Ah. I had expected the second, scalar assignment, to operate on the result of the first assigment. I have now found the place in the book where, by definition, a scalar assignment to the left of a list assignment gets the number of items to the right of the list assignment, not the number of items successfully assigned in that list assignment. (Well, that's clear to me now !)

    Thank you. Perl, eh :-)

    Finally, and for extra points (and points mean prizes), how does one describe the difference between a list and an array ?
    An array is variable. A list is a piece of code that generates a list operator.
    A list is the operator generated from a list in the code.
    A list is the result of an operator or function in list context.

    OK. Well, everybody avoided mentioning the influence of Scalar Context on arrays. But then if lists can only exist in List Context, that wouldn't be worth mentioning :-)

      The list was things that make lists, which are the problematic things Scalar/List context-wise. At that point I was summarising what had been discussed so far...

      But you had discussed arrays and hashes. Are you implying that array slice make lists and arrays don't?

      The omission seems rather "convenient" because it allowed you to cut two exceptions from the "in Scalar Context" list.

      Given that an array returns a list in list context, how do you place that list in scalar context?

      I would argue that, when treated as an rvalue, this is the key difference between a list and an array. Since in Scalar Context the value of the array isn't the list, the case does not arise.

      Exactly. A list can't be produced in scalar context. So how can a list be put into scalar context?

      The point of the question was to point out that "list" is an overloaded term. "List in scalar context" is deceptive, misleading and/or confusing.

      Ah. I had expected the second, scalar assignment, to operate on the result of the first assigment.

      Assignment operators are right-associative. That means that in chain of assignments, the right-most has highest precedence. ** is also right-associative.

      >perl -le"print( 2**3**4 )" 2.41785163922926e+024 >perl -le"print( (2**3)**4 )" 4096 >perl -le"print( 2**(3**4) )" 2.41785163922926e+024

      OK. Well, everybody avoided mentioning the influence of Scalar Context on arrays.

      Two of the three types of list I mentioned in my answer can't be put into scalar context. That makes it a rather minor difference.

        But you had discussed arrays and hashes. Are you implying that array slice make lists and arrays don't?

        Yes. I'd say that an array is a variable whose value is a list. Using the name or some other reference to an array yields that value or its length, depending on Context. In that sense, yes, I was implying that arrays do not make lists. A slice operation, on the other hand, takes a list value and makes a list which is a subset. (I'm open minded, though: if there is, in fact and invisible operator that makes lists out of arrays I would not be surprised.)

        The omission seems rather "convenient" because it allowed you to cut two exceptions from the "in Scalar Context" list.

        I'm sorry you've drawn that conclusion.

        The last item in the list you refer to covers the case of arrays, pointing out that lists and arrays are not identical, and notes the effect of Context. For completeness I could have mentioned hashes, but their relationship to lists is, in my opinion, one step removed, and I did try to keep to the main point, namely Lists in a Scalar Context.

        Exactly. A list can't be produced in scalar context. So how can a list be put into scalar context?

        Just for a moment, let's consider integers and floats as two different sorts of value. Suppose we have the expression:  27 % 4.79. Now, '%' is an integer operation -- one could say it has "Integer Context" -- and the floating point argument is implicitly coerced to an integer, suitable for the '%' operation. At least that is a common understanding of what happens.

        You may argue that the thing which I referred to as a floating point value never was a such, because you cannot have a "Float in Integer Context". That would be consistent with the view that, in Scalar Context:  100 + @r[@p] the thing which looks a lot like a list isn't a list because you cannot have a "List in Scalar Context" (QED).

        "List in scalar context" is deceptive, misleading and/or confusing.

        It is definitely dangerous to assume that all things that return lists in list context will have "List in Scalar Context" semantics. Just as it is would be dangerous to assume that all numeric functions return the same sort of number. So one has to be careful.

        However, where those semantics apply, which is not uncommon, I find it a less confusing notion than "it was never a list, no matter what it looks like". Cooercion is a well understood and common notion. I really don't see why it should not apply to lists. (It does to arrays.)

        Assignment operators are right-associative. That means that in chain of assignments, the right-most has highest precedence. ** is also right-associative.
        >perl -le"print( 2**3**4 )"
        2.41785163922926e+024
        

        Thanks for the clarification. The right-hand '**' happens first, giving 81, then the left-hand '**' takes the 2 and the 81, giving a modestly big result. OK.

        Following that model, in:  $r = ($a, $b) = 0..11 ; the right-hand assignment:  ($a, $b) = 0..11 happens first, so we get ($a=0, $b=1), then that is assigned to $r.... leaving to one side whether ($a, $b) is or isn't a list (given that for the right-hand assignment there's List Context, and in the left-hand one Scalar Context).... since the result is $r=12, right-associativity doesn't appear to be the whole story.

        With thanks to all who pointed me in the right direction here, this is a piece of deeper magic. The right-associativity causes the 0..11 to be evaluated in List Context, and a list assignment is made to ($a, $b). So far, so straightforward. The interesting bit is that the next (left hand), scalar assignment, effectively reaches round the first (right hand) assignment and picks up the length of the list. This is well documented, but the significance of it didn't sink in when I read it however many years ago.

        It's obvious to me now, of course. We're all used to using this magic, for example in: while (my($k, $v) = each(%h)). I admit that I had assumed that this was either because the assignment would leave the lvalue with no more entries in it than were available in the rvalue, or because the $v was undefined -- though I never tested either. I live and learn. (Though, sadly, wisdom eludes me.)

        Ah well. It has been said that "There is no spoon". But some say it's worse than that (Jim), by extension there's no cutlery, no kitchen utensils, no stove, no kitchen and pretty soon I can expect to starve to death. I think I'll go and do something really dangerous now, I'll take away some brackets and to blazes with the sign.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (9)
As of 2024-04-19 07:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found