5

There is a lie that a list in scalar context yields the last element of the list. This is a lie because (as the saying goes) you can't have a list in scalar context. What looks like a list in scalar context is really the comma operator in scalar context and it has different behavior in scalar context.

However, there seems to be a loop hole in this logic: the null list (sometimes called the empty list). The characters () are defined to be the null list by perldoc perlglossary. The construct

my $s = ();

is valid code and returns undef to $s. This does not appear to be documented anywhere in perldoc (I haven't checked the Camel), but lots of code counts on it, so I think it is here to stay.

Now that the preamble is done, here is the question: if we cannot have a list in scalar context, then what do we call the empty list in scalar context and what is the rational for not calling it a list (since there are no commas to be in scalar context)?

If you are enjoying this question, you may also like the discussion going on in P5P.

Chas. Owens
  • 64,182
  • 22
  • 135
  • 226
  • 1
    Interesting question. Just speculating, so I'm putting this in a comment: are the parentheses in your example really an empty list or are they simply parentheses in this vein: `my $x = (4 * 3) + 1;`? I ask, because when I trace through the hyperlinks in the perlglossary (empty list > list value > list context), even the empty list appears to hinge upon the existence of list context. – FMc Aug 06 '11 at 17:29
  • @FMc A valid point. The parentheses in `my $s = ()` might not be an empty list, but a valueless expression (which is null). – Chas. Owens Aug 06 '11 at 17:32
  • Should it result in an error instead? Odd, yes, but... seems like a sensible enough outcome without terminating the program abruptly. –  Aug 06 '11 at 17:33
  • 1
    @pst The trick is that the null list is used a lot in boolean context to mean false. `perldoc perlsyn` even says "The number 0, the strings '0' and '' , the empty list () , and undef are all false in a boolean context." This is the crux of the problem. `perlsyn` says you can have an empty list in scalar context, but you can't have a list in scalar context (they don't exist in Perl 5). – Chas. Owens Aug 06 '11 at 17:40

2 Answers2

7

List is a very generic word. You could possibly be referring to the list operator or to a list value.

There is no comma in the code, so there is no list operator.

There is no list context in the code, so there is no list value.

Therefore, there is no list in

my $s = ();

Parentheses never create a list

(Only indirectly when on the LHS of an assignment operator.)

what do we call the empty list in scalar context

Perl calls it a "stub" (as shown below), and that's truly what it is. It's a placeholder in the code where putting literally nothing would be disallowed.

The stub is represented by "empty parentheses", so that's another name for it.

I call it bad code. If you want to assign undef, assign undef.

There is a lie that a list in scalar context yields the last element of the list.

No, that's true. List values cannot exist in scalar context, so that leaves the list operator.

The list operator aka the comma operator returns the last element of the list in scalar context.


Compare the following. No mention of list:

>perl -MO=Concise -e"my $s = ();"
6  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
5     <2> sassign vKS/2 ->6
3        <0> stub sP ->4
4        <0> padsv[$s:1,2] sRM*/LVINTRO ->5
-e syntax OK

There is a mention of a list

>perl -MO=Concise -e"my @a = ();"
7  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
6     <2> aassign[t2] vKS ->7
-        <1> ex-list lK ->4
3           <0> pushmark s ->4
-           <0> stub lP ->-
-        <1> ex-list lK ->6
4           <0> pushmark s ->5
5           <0> padav[@a:1,2] lRM*/LVINTRO ->6
-e syntax OK

...and it has nothing to do with the parens

>perl -MO=Concise -e"my @a = 's';"
8  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
7     <2> aassign[t2] vKS ->8
-        <1> ex-list lK ->5
3           <0> pushmark s ->4
4           <$> const[PV "s"] s ->5
-        <1> ex-list lK ->7
5           <0> pushmark s ->6
6           <0> padav[@a:1,2] lRM*/LVINTRO ->7
-e syntax OK
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • I think you are misusing the term [list operator](http://goo.gl/BHIxt). It isn't bad code (well `$s = ()` probably is, but `if ( f() )` where `f` returns a null list is standard practice). The lie is that a list can ever be in list context (it can't because there is no such beast in Perl 5), not that it yields the last item. `perl` may call it a `stub`, but Perl calls it the null list or the empty list. Interestingly, in the second example `()` is still a stub, not a list (the stub is a (non-)value in the list). `perl -MO=Concise -e '((),5,())'` is also interesting. – Chas. Owens Aug 07 '11 at 10:39
  • @Chas. Owens, Re "The lie is that a list can ever be in list context", No it's not. The list op (aka comma op) can definitely be used in scalar context. It just won't return a list. Do ` perl -MO=Concise -e "scalar('a','b')"` and you'll see `list s`. The "s" is for "scalar". – ikegami Aug 07 '11 at 19:07
  • @Chas. Owens, As for `if (f())`, that seems really wrong too. If `f` is returning `()`, that means it can return `undef` as a "true" value. `if (f())` should be `if (() = f())` or `f()` shouldn't be returning `()`. Again, bad code. – ikegami Aug 07 '11 at 19:10
  • @Chas. Owens, Re "I think you are misusing the term list operator", I'm referring to *the* list operator, not this slang for operators that process arbitrary lists. See perlop. – ikegami Aug 07 '11 at 19:19
  • Reread `perlop` yourself, the comma operator is the comma operator (it is never referred to as the list operator). There is no "the list operator". List operator is the technical term for an n-ary function call that does not use parentheses. – Chas. Owens Aug 08 '11 at 01:02
  • @Chas. Owens, ok, fine, it's only called list operator internally (see -MO=Concise). And in common parlance. Basically everywhere except perlop. So what's your point again? – ikegami Aug 08 '11 at 21:26
  • @Chas. Owens, So what do you call the operator used inside these parens? `f(1,2,3)` You're the only person whose ever even hinted to me it could be something other than a list. – ikegami Aug 08 '11 at 21:48
  • I see two comma operators building a list, or more simply a list. I have never heard anyone call a comma a list operator. Most people seem to not even be aware it is an operator. The impression I get is that they think it is part of the syntax of building a list. The notion that `(3,2,1)` is a list will carry you pretty far, until you try to understand why it returns `1` and you get warnings about `3` and `2` being in void context, or `perl -E'sub f{say$a=wantarray?1:defined $a?0:-1}$s=(f,f);@a=(f,f)` prints what it does. At that point you have to understand the comma operator and how it works – Chas. Owens Aug 09 '11 at 00:09
  • @Chas. Owens, Sounds like you've come to agree with me? It's an operator that most people call list. As such, I was quite justified in covering that base. – ikegami Aug 09 '11 at 02:13
  • Depends, do you believe "A list in scalar context yields the last element of the list." is a lie? If you don't then we aren't in agreement yet. I do think it is a useful mental model for beginners and covers most of the common use cases, but the lie fails when confronted with `perl -E '@a=qw/x y z/; $a = (qw/a b c/, @a); say $a; say +(qw/a b c/, @a)[-1]'`. If the first case were a list, then `@a` would interpolate into it (as it does in the second example). – Chas. Owens Aug 09 '11 at 13:10
  • @Chas. Owens, You're obviously talking about a list operator (since list values cannot exist in scalar context), in which case a list is a list of expressions (1: `qw/ a b c/`, 2: `@a`). You seem to be thinking it's some kind of list of scalars, but that would assume the creation of a list value in scalar context. A list in scalar context does indeed yield the last element of the list (`@a`), or rather what it evaluates to (since expressions can't be returned). There is a lie there, and it's "If the first case were a list, then `@a` would interpolate into it". You clearly proved otherwise. – ikegami Aug 09 '11 at 15:47
  • No, I have clearly proven that it isn't a list (and hence the statement is a lie). Lists are defined as ["An ordered set of scalar values."](http://perldoc.perl.org/perlglossary.html#list) and ["when a LIST is evaluated, each element of the list is evaluated in list context, and the resulting list value is interpolated into LIST just as if each individual element were a member of LIST. Thus arrays and hashes lose their identity in a LIST"](http://goo.gl/ah51k). Reread the comma operator in perlop, the first two paragraphs spell it out plainly; only in list context does comma create a list. – Chas. Owens Aug 09 '11 at 15:51
  • @Chas. Owens, "An ordered set of scalar values." is the definition of a list *value*. List values cannot exist in scalar context. List values do not return anything, ever, since they are not operators. The sentence you are asking about has nothing to do with list values. You are employing a fallacy, using list to mean both list operator and list value, then making conclusions about one based on the other. The only thing that could be referring to is the list *operator* aka the comma operator, and it does return its last element, or more precisely, the value to which it evaluates. – ikegami Aug 09 '11 at 15:55
  • @Chas.Owens let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/2284/discussion-between-ikegami-and-chas-owens) – ikegami Aug 09 '11 at 16:01
  • I have always meant list value when I said list. What else would it have meant? A list is created by the comma (not list) operator when that operator is in list context and only when it is in list context. The thing that looks like a list in this expression `$s=(1,2,3)` is not a list any more than `$s=(1+2+3)` is. The return value of `(1,2,3)` is the result of the operands `1` being evaluated in void context and `2,3` being evaluated in scalar context. The return value of `2,3` is the result of `2` being evaluated in void context and `3` being evaluated in scalar context. No list in sight. – Chas. Owens Aug 09 '11 at 17:18
  • @Chas. Owens, Re "The thing that looks like a list in this expression $s=(1,2,3) is not a list", is not true. Perl does indeed consider it a list and you know it. You even admitted that most people consider a list too. You're just contradicting yourself now. – ikegami Aug 09 '11 at 17:45
  • @Chas. Owens, Re "I have always meant list value when I said list.". That's not true at all. All of your questions have been about the list operator. "A list in scalar context yields the last element of the list.", "`$a = (qw/a b c/, @a);`", etc. – ikegami Aug 09 '11 at 17:50
1

It's more like a valueless expression which is equivalent to undef. Some more examples:

$ perl -we 'print scalar( () )'
Use of uninitialized value in print at -e line 1.

$ perl -we 'print 0+()'
Use of uninitialized value in addition (+) at -e line 1.
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • 1
    FMc made this point in the comments, and it is compelling. I guess I should splunk into the internals to figure out what the `perl` thinks is going on. – Chas. Owens Aug 06 '11 at 22:23
  • @Chas. Owens, it creates a `stub` operator (but no list operator). See my answer. – ikegami Aug 07 '11 at 05:12