// must evaluate its left-hand side operator in scalar context since it requires a scalar to evaluate for defined-ness.
@a returns the number of elements the array contains in scalar context.
So @a // ... always returns the number of elements in @a (since all numbers are defined values).
The concepts of defined-ness or truth-ness aren't defined for a sequence of scalars ("list") as a whole. They only apply to individual scalars. As such, //, &&, and, ||, or, !, not and ?: require a scalar from their left-most operand, so they evaluate it in scalar context. xor needs to test the truth of both of its operands, and thus evaluates both in scalar context.
$ perl -M5.010 -e'
sub cx { print wantarray ? " list " : " scalar"; $_[0] }
print "// "; @a = cx($u) // cx(); say "";
print "&& "; @a = cx(0) && cx(); say "";
print "and"; @a = ( cx(1) and cx() ); say "";
print "|| "; @a = cx(0) || cx(); say "";
print "or "; @a = ( cx(0) or cx() ); say "";
print "xor"; @a = ( cx(0) xor cx(0) ); say "";
print "! "; @a = ! cx(); say "";
print "not"; @a = not cx(); say "";
print "?: "; @a = cx() ? 0 : 0;
@a = 1 ? cx() : 0;
@a = 0 ? 0 : cx(); say "";
'
// scalar list
&& scalar
and scalar list
|| scalar list
or scalar list
xor scalar scalar
! scalar
not scalar
?: scalar list list
You might be under the incorrect impression that @a always returns a list of its elements, and that this gets coerced into a count when evaluated in scalar context. But that's not the case.
There's simply no such thing as a list. When we say "evaluates to a list" or "returns a list", we simply mean "adds zero or more scalar to the stack". There's absolutely no difference between return a scalar and returning "a list of one scalar". Both refer to adding a scalar to the stack.
Since there's no list data structure being returned, there's nothing that can be magically coerced to a scalar in scalar context; its up to every operator to return a single scalar when evaluated in scalar context. This permits each operator to choose what they want to return in scalar context. It varies greatly.
In short, @a returns the number of elements in scalar context, not the elements it contains like it does in list context.
+-------------------------- (Scalar context) Returns 3
| +------------- (List context) Returns three scalars
| |
vvvv vvvvvvvv
() = @row // (10,20,30);
+-------------------------- (Scalar context) Returns 3
| +------------------- (List context) Returns three scalars
| | +------- (List context) Returns three scalars
| | |
vvvv vvvv vvvvvvvv
() = @row ? @row : (10,20,30);
Finally, let's analyze @row // ....
We've already established that @row is evaluated in scalar context in the above, and that it returns the number of elements in the array in array when it does.
Well, numerical values are necessarily not undef, so they are all defined. So that means that the right-hand size of @row // ... will never get evaluated. You might as well have written scalar(@row).