List Context in a Boolean Expression

H

h3xx

I have a question about when things are and aren't taken to be a list
when doing boolean comparisons. I tested the following code:

my @foo = qw/ one two three /;
my @bar = ();

my @baz = @bar || @foo;
print "@baz\n";

This produces "one two three." Hence, we know that a list CAN be
returned from a boolean expression. I tried it the other way:

my @baz = @foo || @bar;
print "@baz\n";

This produced "3," the scalar evaluation of @foo. This is the same for
any amount of parentheses and using the "or" operand instead of "||."
Now, what happened?
 
J

Jürgen Exner

h3xx said:
I have a question about when things are and aren't taken to be a list
when doing boolean comparisons. I tested the following code:

my @foo = qw/ one two three /;
my @bar = ();

my @baz = @bar || @foo;
print "@baz\n";

This produces "one two three." Hence, we know that a list CAN be
returned from a boolean expression. I tried it the other way:

my @baz = @foo || @bar;
print "@baz\n";

This produced "3," the scalar evaluation of @foo. This is the same for
any amount of parentheses and using the "or" operand instead of "||."
Now, what happened?

See The Fine Manual: perldoc perlop, section "C-style Logical Or":
The "||" and "&&" [...] return the last value evaluated.
and
In particular, this means that you shouldn't use this for selecting
between two aggregates for assignment:
@a = @b || @c; # this is wrong

jue
 
H

h3xx

h3xx said:
I have a question about when things are and aren't taken to be a list
when doing boolean comparisons. I tested the following code:
my @foo = qw/ one two three /;
my @bar = ();
my @baz = @bar || @foo;
print "@baz\n";
This produces "one two three." Hence, we know that a list CAN be
returned from a boolean expression. I tried it the other way:
my @baz = @foo || @bar;
print "@baz\n";
This produced "3," the scalar evaluation of @foo. This is the same for
any amount of parentheses and using the "or" operand instead of "||."
Now, what happened?

See The Fine Manual: perldoc perlop, section  "C-style Logical Or":
   The "||" and "&&" [...] return the last value evaluated.
and
    In particular, this means that you shouldn't use this for selecting
    between two aggregates for assignment:
        @a = @b || @c;              # this is wrong

jue

Ah. Thank you. I guess I'll just have to solve the problem using the
tried-and-true trinary method:

my @foo = qw/ one two three /;
my @bar = ();

my @baz = @bar ? @bar : @foo;
 
M

Michael Carman

Jürgen Exner said:
See The Fine Manual: perldoc perlop, section "C-style Logical Or":
The "||" and "&&" [...] return the last value evaluated.
and
In particular, this means that you shouldn't use this for selecting
between two aggregates for assignment:
@a = @b || @c; # this is wrong

That's the warning, but I don't think you quoted quite enough to explain
the behavior. I had to look it up myself because it seemed odd to me
that the left and right operands wouldn't be evaluated in the same
(scalar vs. list) context.

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

So the expression

@baz = @bar || @foo;

really means

@baz = scalar @bar || @foo;

The left operand is always evaluated in scalar context (it's a boolean
test) but the right operand takes it's context from the expression it's
used in.

The right way to write this is:

@baz = @bar ? @bar : @foo;

-mjc
 
J

Jürgen Exner

Michael Carman said:
Jürgen Exner said:
See The Fine Manual: perldoc perlop, section "C-style Logical Or":
The "||" and "&&" [...] return the last value evaluated.
and
In particular, this means that you shouldn't use this for selecting
between two aggregates for assignment:
@a = @b || @c; # this is wrong

That's the warning, but I don't think you quoted quite enough to explain
the behavior.

Well, no, of course I didn't. It was a teaser ...
I had to look it up myself because it seemed odd to me

.... to have you do exactly that. After all, I assume you are old enough
not to need someone to read the man pages to you.

jue
 
M

Michael Carman

Jürgen Exner said:
Well, no, of course I didn't. It was a teaser ...


... to have you do exactly that. After all, I assume you are old
enough not to need someone to read the man pages to you.

I read this newsgroup for discussions about Perl, not to get homework
assignments. While I can RTFM I'd rather discuss the behavior,
particularly when that behavior is unintuitive.

Getting back on-topic...

It's obvious that the left operand must be evaluated in scalar context
because it's a boolean test. I would have expected the || operator to
impose scalar context on the right operand as well; that just seems like
the obvious thing to do. I find the (potential) propagation of list
context curious. Was it a deliberate design decision or just a side
effect? If it was deliberate then someone must have thought that it
might be useful. Has anyone ever found an application for this behavior?
I'm having a hard time envisioning a situation where

@foo = $bar || @baz;

is useful. Does anyone have an example?

-mjc
 
D

Dr.Ruud

Michael Carman schreef:
I'm having a hard time envisioning a situation where
@foo = $bar || @baz;
is useful.


Then use it in a JAPH. Why did you write "$bar"?
 
X

xhoster

Michael Carman said:
I read this newsgroup for discussions about Perl, not to get homework
assignments. While I can RTFM I'd rather discuss the behavior,
particularly when that behavior is unintuitive.

Getting back on-topic...

It's obvious that the left operand must be evaluated in scalar context
because it's a boolean test.

I wouldn't say it *must* do this. It could evaluate it in a list
context, then treat that resulting list as false (for purposes of
short-circuiting) if it is empty.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
M

Michael Carman

Dr.Ruud said:
Michael Carman schreef:



Then use it in a JAPH.

I'm rather hoping that language design decisions aren't being influenced
by how useful a feature would be in obfuscated code contests. :p
Why did you write "$bar"?

To highlight that the left operand to || is evaluated in scalar context.

Additionally, since perlop explicitly says

@a = @b || @c; # this is wrong

Then presumably the right[1] syntax that would make use of list context
to the right operand would be

@a = $b || @c;

I can't think of any idioms that would make use of that, though.

[1] for some definition of "right"
 
B

Ben Bullock

I have a question about when things are and aren't taken to be a list
when doing boolean comparisons. I tested the following code:

my @foo = qw/ one two three /;
my @bar = ();

my @baz = @bar || @foo;
print "@baz\n";

The || forces @bar into scalar context. scalar(@bar) = 0, so the left
hand side is false, so Perl evaluates the right hand side.
This produces "one two three." Hence, we know that a list CAN be
returned from a boolean expression. I tried it the other way:

my @baz = @foo || @bar;
print "@baz\n";

The || forces @foo into scalar context. scalar (@foo) = 3, so Perl never
evaluates the right hand side.
This produced "3," the scalar evaluation of @foo. This is the same for
any amount of parentheses and using the "or" operand instead of "||."
Now, what happened?

You've really answered your own question. This is the behaviour of ||,
forces what's on the left of it into scalar context.
 

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,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top