Home > database >  Perl list in boolean (scalar) context in while loop
Perl list in boolean (scalar) context in while loop

Time:02-05

I'm staring at this code in perl LWP::Protocol.pm and I don't understand how the loop would ever exit:

 while ($content = &$collector, length $$content) {
     $content_size  = length($$content);
     # more here
 }

In my interpretation, I am thinking this is a list of 2 elements in scalar context, so the result that the while loop is testing is the length of the list, which is always 2 and never false. How does this really work?

CodePudding user response:

Please have a look at the operator precedence in the documentation. There you'll see that = has a higher precedence than ,. This means first it does $content = &$collector due to the higher precedence of = compared to ,. Then it does length $$content.

Continuing with the documentation about the Comma Operator one will find:

Binary "," is the comma operator. In scalar context it evaluates its left argument, throws that value away, then evaluates its right argument and returns that value.

Thus the result in this case will be the right one, i.e. length $$content. This will then be used as the condition inside while.

CodePudding user response:

I am thinking this is a list of 2 elements in scalar context

Correct.

Technically, the documentation calls it the comma operator when it's used in scalar context,[1] but the operator is still called list internally.

The only real problem with that statement is the choice of word element. Operators have operands (which are expressions), not elements. Element is used to refer to the members of data structures, which isn't applicable here.

so the result that the while loop is testing is the length of the list,

No.

You think some kind of list data structure gets produced, and it's then coerced into a scalar. This is a common misunderstanding, but it's not how context work at all. Scalar context doesn't coerce lists into their count; scalar context causes the operators to return a scalar from the start.[3] An operator in scalar context must produce exactly one scalar. And what that scalar is up to each individual operator.

A list/comma operator in scalar context doesn't return the length of anything. It evaluates each of its operands but the last in void context.[2] Then, it evaluates the last one in scalar context and returns the resulting scalar.

In other words,

scalar( EXPR, EXPR )

is similar to

scalar( do { EXPR; EXPR } )

  1. It also goes out of its way to call it a binary operator, when 1) people don't think of it a binary operator, the generated operator isn't a binary operator, and 3) it makes absolutely no difference if it's a binary operator or not. Weird.

  2. If the list is the last operand of a sub or the operand of a return, and if the sub is evaluated in scalar context, they will be evaluated in scalar context instead. This is a basically a WONTFIX bug.

  3. In fact, there's no such thing as lists in that sense even in list context. When we say "passes a list" or "returns a list", we simply mean "adds a number of scalars to the stack". No "list" gets created.

  •  Tags:  
  • Related