views:

147

answers:

3

When I try this:

$a = 1;
$b = 2;
print ($a && $b) . "\n";

The result is 2. Why?

+2  A: 

Because the && operator evaluates the right operand and returns the result when the left operand evaluates to true.

Benoit
+15  A: 

Quote perlop:

The "||", "//" and "&&" operators return the last value evaluated (unlike C's "||" and "&&", which return 0 or 1).

The resulting 2 is considered true by Perl, so that when you use the && operator in a logical condition, everything works as expected. The added bonus is that you can use the logical operators in other contexts as well:

sub say_something {
    say shift || 'default';
}

say_something('foo'); # prints 'foo'
say_something(); # prints 'default'

Or even as flow modifiers:

my $param = shift || die "Need param!";
-f $file && say "File exists.";

In the last two examples it’s good to realize that they could not work if the && and || operators did not short-circuit. If you shift a true value in on first line, there is no point evaluating the right side (die…), since the whole expression is true anyway. And if the file test fails on the second line, you don’t need to evaluate the right side again, since the overall result is false. If the logical operators insisted on evaluating the whole expression anyway, we could not use them this way.

zoul
nicely explained
Nic Gibson
+11  A: 

That's how the && operator works: if the left-hand argument evaluates as true, the value of the expression is that of the value of the right-hand argument. This is covered on the perlop page.

However, you've also let yourself open to a much more subtle problem. You'll find that the newline doesn't get printed. This is because if you put an expression in brackets after print (or any other function name) the arguments passed to print are just those in the brackets. To get notice of this, make sure you switch on warnings. Put these lines at the top of each program:

#!/usr/bin/perl -w

use strict;

until you understand them enough to decide for yourself whether to continue with them. :-)

In your case, you'll get this:

print (...) interpreted as function at p line 7.
Useless use of concatenation (.) or string in void context at p line 7.
Tim
Thank you for solve my subtle problem :)
Atom Skaa ska Hic
I'm use Windows. "#!/usr/bin/perl -w" can works with ?
Atom Skaa ska Hic
It should do - I believe that Perl picks up the switches itself from the top line to cope with this sort of situation.
Tim
Yes: "The #! line is always examined for switches as the line is being parsed. Thus, if you're on a machine that allows only one argument with the #! line, or worse, doesn't even recognize the #! line, you still can get consistent switch behavior regardless of how Perl was invoked, even if -x was used to find the beginning of the program." -- http://perldoc.perl.org/perlrun.html
Tim
Okay, I'm got an errors.
Atom Skaa ska Hic
Great! In this sort of case, errors are your friend - you'll learn as you work out what's causing them, and how to avoid them. Do come back when you want help or advice. Good luck. :-)
Tim
"use warnings;" is a modern way to turn warnings on
Alexandr Ciornii
@Alexandr Oh yes, good point. I have a vague recollection that the `-w` switch and `use warnings;` aren't *quite* identical, but I might be wrong. Good call though. :-)
Tim
@Tim: The primary difference is that `-w` is global, turning on all warnings unconditionally for the whole program, while `use warnings` is lexical, allowing you to have warnings enabled in some scopes and disabled in others, and also allows you to turn certain types of warnings on while others are off instead of being all-or-nothing.
Dave Sherohman
@Dave Thank you. That makes a lot of sense.
Tim
avoid calling () brackets...see http://en.wikipedia.org/wiki/Brackets#Usage
ysth
@ysth Thanks for the reference. Being in the UK, I will continue to call `(` and `)` brackets, and describe them as *round brackets* when I need to ensure there is no ambiguity. But thank you for drawing my attention to the fact that some people may need more help than others in appreciating the difference.
Tim