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