Evaluation context of C-style Logical And/Or

T

truexueweizhong

I'm really confused about the following result:

$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a || @b; print @c'
2
-----------seemed to be scalar context

$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a or @b; print @c'
a1a2
----------seemed to be list context

what's the rules govering this issue?
the sentence in perlop say it not clearly, only one sentence:

Scalar or list context propagates down to the right operand if
it is evaluated.
and

Logical or and Exclusive Or

Binary "or" returns the logical disjunction of the two
surrounding
expressions. It's equivalent to || except for the very low
precedence.


But what's the explaination of sampling code?
 
T

truexueweizhong

$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a or @b; print @c'

Now i know this one, because
@c = @a or @b
is equal to
(@c = @a) or @b
so it's not amazing any more.

But I'm still confused about the following result:

$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a && @b; print @c'
b1b2
------------- && , list context
$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a || @b; print @c'
2
------------- ||, scalar context
 
A

axel

I'm really confused about the following result:
$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a || @b; print @c'
2
-----------seemed to be scalar context

$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a or @b; print @c'
a1a2
----------seemed to be list context
But what's the explaination of sampling code?

An array in scalar context returns the number of elements

An array in scalar context returns the number of elements. So your first
example:

@c = @a || @b;

evaluates to:

@c = 2 || 2;

making @c an array with the one element '2';

In the second example '=' has a higher precendence than the 'or' and so
the values of the array @a are copied to @c.

Axel
 
J

John W. Krahn

I'm really confused about the following result:

$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a || @b; print @c'
2
-----------seemed to be scalar context

$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a or @b; print @c'
a1a2
----------seemed to be list context

what's the rules govering this issue?

Don't use '||' or 'or' with arrays or lists or hashes, only with scalars.

$ perl -wle '@a = ( "a1", "a2" ); @b = ( "b1", "b2" ); @c = @a || @b; @a = ();
@d = @a || @b; print for "@c", "@d"'
2
b1 b2
$ perl -wle '@a = ( "a1", "a2" ); @b = ( "b1", "b2" ); @c = @a or @b; @a = ();
@d = @a or @b; print for "@c", "@d"'
Useless use of a variable in void context at -e line 1.
Useless use of a variable in void context at -e line 1.
a1 a2



Note that:

@c = @a or @b;

and:

@c = @a;

do the same thing because of the low precedence of 'or' (see the warning
messages above.)

However the conditional operator does work with lists, arrays and hashes so
this will do what you want:

@c = @a ? @a : @b;

the sentence in perlop say it not clearly, only one sentence:

Scalar or list context propagates down to the right operand if
it is evaluated.
and

@c = @a || @b;

'@c' is an array so there is list context to the right of '='. '@a ||'
determines whether '@a' is "true" or "false". In order to determine if '@a'
is "true" or "false" it must be evaluated in scalar context. If it is "true"
the results of that evaluation is then assigned to '@c'. If it is "false"
then the list context is propagated through to '@b'.



John
 
T

truexueweizhong

@c = @a || @b;

'@c' is an array so there is list context to the right of '='. '@a ||'
determines whether '@a' is "true" or "false". In order to determine if '@a'
is "true" or "false" it must be evaluated in scalar context. If it is "true"
the results of that evaluation is then assigned to '@c'. If it is "false"
then the list context is propagated through to '@b'.

So what's the difference between
@c = @a || @b
and
@c = @a && @b

In the latter case, the Perl evaluate @a in LIST context rather than
SCALAR, why?
 
J

John W. Krahn

An array in scalar context returns the number of elements

An array in scalar context returns the number of elements. So your first
example:

@c = @a || @b;

evaluates to:

@c = 2 || 2;

Actually it evaluates to:

@c = 2 || @b;




John
 
J

John W. Krahn

So what's the difference between
@c = @a || @b
and
@c = @a && @b

In the latter case, the Perl evaluate @a in LIST context rather than
SCALAR, why?

No, it evaluates @a in scalar context:

$ perl -wle '@a = ( "a1", "a2" ); @b = ( "b1", "b2" ); @c = @a && @b; @a = ();
@d = @a && @b; print for "@c", "@d"'
b1 b2
0


Otherwise it would print:

b1 b2
a1 a2

instead.




John
 
T

truexueweizhong

$ perl -wle '@a = ( "a1", "a2" ); @b = ( "b1", "b2" ); @c = @a && @b; @a = ();
@d = @a && @b; print for "@c", "@d"'
b1 b2
0

So I believe now that @a is evalutated in SCALAR context.
But why @b is evaluated in LIST context?
 
J

John W. Krahn

So I believe now that @a is evalutated in SCALAR context.
But why @b is evaluated in LIST context?

Because '@c =' forces list context on the assignment. The logical operators
are left associative so they only affect the context of the operand on the left.


John
 
T

truexueweizhong

Because '@c =' forces list context on the assignment. The logical operators
are left associative so they only affect the context of the operand on the left.

Yes, you tell me the perlop truth now.

Thanks so much.
Best regards
Weizhong Xue
Shanghai/China
 
A

anno4000

Now i know this one, because
@c = @a or @b
is equal to
(@c = @a) or @b
so it's not amazing any more.

But I'm still confused about the following result:

$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a && @b; print @c'
b1b2
------------- && , list context
$ perl -e '@a = (a1,a2); @b = (b1,b2); @c = @a || @b; print @c'
2
------------- ||, scalar context

Re-read the documentation on && and || in perldoc. It's in there,
though obliquely. The second sentence says:

Scalar or list context propagates down to the right operand
if it is evaluated.

The left operand isn't mentioned, meaning it is evaluated in scalar
context. Now, with the && operation the result is determined by the
right operator which is in list context. With ||, the result is
the left operator which is in scalar context. Hence the difference.

By induction it follows that only the last operand in a chain of
&& and || can ever be in list context.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,231
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top