Velocity Reviews > Perl > && is not an lvalue

# && is not an lvalue

xhoster@gmail.com
Guest
Posts: n/a

 07-31-2008
It seems like almost everything in Perl is an lvalue. So why isn't the
result of && an lvalue?

I wanted to do this:
(\$h{\$big}{\$nasty}[\$dereferencing]{operation(\$x)}{\$done}[here(y)]and die)=6;

Obviously, that just isn't the way perl was implemented. But is there a
reason that "?:" yields an lvalue but && doesn't?

Thanks,

Xho

--
The costs of publication of this article were defrayed in part by the
this fact.

Ben Morrow
Guest
Posts: n/a

 07-31-2008

Quoth http://www.velocityreviews.com/forums/(E-Mail Removed):
> It seems like almost everything in Perl is an lvalue. So why isn't the
> result of && an lvalue?
>
> I wanted to do this:
> (\$h{\$big}{\$nasty}[\$dereferencing]{operation(\$x)}{\$done}[here(y)]and die)=6;
>
> Obviously, that just isn't the way perl was implemented. But is there a
> reason that "?:" yields an lvalue but && doesn't?

Perhaps because it's not entirely clear which operand would be returned
when both are true or both false? That doesn't apply to your case, of
course, since one of them is 'die' and can never be returned, but perl
doesn't know that.

Which one you actually get is rather confusing. If either is false, you
get that one; if both are false, you get the first; and if both are
true you get the second. || is the other way around: both false gives
the second operand, and both true the first. I suppose it makes sense
when you consider the short-circuiting.

Oddly, you *can* take a ref to the result of && (which is in fact an
lvalue), which means

\${\( \$x and die )} = 6;

*does* work as you expect, despite being hideously ugly.

Even stranger, while do { \$x } returns \$x (though of course you can't
assign to it directly), if the expression inside the 'do' gets too
complicated it starts returning a copy instead:

~% perl -le'print \do { \$x }; print \\$x'
SCALAR(0x8100be0)
SCALAR(0x8100be0)
~% perl -le'print \do { \$x and 1 }; print \\$x'
SCALAR(0x8100be0)
SCALAR(0x8100be0)
~% perl -le'print \do { \$x and die }; print \\$x'
SCALAR(0x810016c)
SCALAR(0x8100be0)
~% perl -le'print \do { \$x; \$x }; print \\$x'
SCALAR(0x810016c)
SCALAR(0x8100be0)

The point at which it switches over appears to be when the do block gets
its own ENTER/LEAVE ops rather than just being a scope.

A clean way around the problem is to use Data::Alias:

use Data::Alias;

alias my \$tmp = \$h{......}
and die ...;
\$tmp = 6;

Ben

--
All persons, living or dead, are entirely coincidental.
(E-Mail Removed) Kurt Vonnegut

Michael Carman
Guest
Posts: n/a

 08-01-2008
Ben Morrow wrote:
> Quoth (E-Mail Removed):
>>
>> is there a reason that "?:" yields an lvalue but && doesn't?

>
> Perhaps because it's not entirely clear which operand would be
> returned when both are true or both false?

&& is defined to return the last thing evaluated. How is that not clear?

> Which one you actually get is rather confusing.

I don't think that the behavior of the operator isn't confusing at all.
Any code that makes use of that behavior is likely to be if only because
it's so rarely used.

-mjc

xhoster@gmail.com
Guest
Posts: n/a

 08-01-2008
Ben Morrow <(E-Mail Removed)> wrote:
> Quoth (E-Mail Removed):
> > It seems like almost everything in Perl is an lvalue. So why isn't the
> > result of && an lvalue?
> >
> > I wanted to do this:
> > (\$h{\$big}{\$nasty}[\$dereferencing]{operation(\$x)}{\$done}[here(y)]and
> > die)=6;
> >
> > Obviously, that just isn't the way perl was implemented. But is there
> > a reason that "?:" yields an lvalue but && doesn't?

>
> Perhaps because it's not entirely clear which operand would be returned
> when both are true or both false? That doesn't apply to your case, of
> course, since one of them is 'die' and can never be returned, but perl
> doesn't know that.
>
> Which one you actually get is rather confusing. If either is false, you
> get that one; if both are false, you get the first; and if both are
> true you get the second. || is the other way around: both false gives
> the second operand, and both true the first. I suppose it makes sense
> when you consider the short-circuiting.

Yep. And I was consider short-circuiting, so I didn't find it all that
confusing. Off the top of my head, I can't think if anything I'd use this
for that didn't have a die as the second. (but I probably wouldn't use
that construct in anything except one-offs or one-liners, anyway.)

>
> Oddly, you *can* take a ref to the result of && (which is in fact an
> lvalue), which means
>
> \${\( \$x and die )} = 6;
>
> *does* work as you expect, despite being hideously ugly.

Yeah, I did that experiment myself. But I didn't make the valid deduction
that you have, that it actually is an l-value, just an l-value which
the compiler pitches a fit over. Which makes it even stranger to me.
It seems like the programmers must have went out of their way to make
this syntax error happen, rather than it being a natural consequence of
something else.

Xho

--
The costs of publication of this article were defrayed in part by the
this fact.