Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

List Context in a Boolean Expression

0 views
Skip to first unread message

h3xx

unread,
Aug 16, 2008, 5:05:47 AM8/16/08
to
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ürgen Exner

unread,
Aug 16, 2008, 8:21:23 AM8/16/08
to

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

h3xx

unread,
Aug 16, 2008, 5:21:12 PM8/16/08
to
On Aug 16, 7:21 am, Jürgen Exner <jurge...@hotmail.com> wrote:

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;

Michael Carman

unread,
Aug 16, 2008, 7:51:38 PM8/16/08
to
Jürgen Exner wrote:
>
> 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ürgen Exner

unread,
Aug 16, 2008, 8:40:28 PM8/16/08
to
Michael Carman <mjca...@mchsi.com> wrote:
>Jürgen Exner wrote:
>>
>> 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

Michael Carman

unread,
Aug 17, 2008, 10:41:35 AM8/17/08
to
Jürgen Exner wrote:

> Michael Carman <mjca...@mchsi.com> wrote:
>> 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.

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

Dr.Ruud

unread,
Aug 18, 2008, 7:25:57 AM8/18/08
to
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"?

--
Affijn, Ruud

"Gewoon is een tijger."

xho...@gmail.com

unread,
Aug 18, 2008, 12:38:57 PM8/18/08
to
Michael Carman <mjca...@mchsi.com> wrote:
> Jürgen Exner wrote:
> > Michael Carman <mjca...@mchsi.com> wrote:
> >> 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.
>
> 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.

Michael Carman

unread,
Aug 19, 2008, 6:59:26 PM8/19/08
to
Dr.Ruud wrote:
> Michael Carman schreef:
>
>> I'm having a hard time envisioning a situation where
>> @foo = $bar || @baz;
>> is useful.
>
>
> 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"

Ben Bullock

unread,
Sep 1, 2008, 8:52:19 AM9/1/08
to
On Sat, 16 Aug 2008 02:05:47 -0700, h3xx wrote:

> 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.

0 new messages