if .. then .. else shorthand problem

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

•  Subject
• Author
• Posted on

I've only just started using the shorthand for the "if .. then .. else"
statement: (test) ? this : or_that;

Here's what I have:

use strict;
use warnings;

my \$weight = 40.18;

my \$half_kilos = (( int(\$weight) -30 ) * 2);
print "\$half_kilos\n";
if ( ((\$weight - 30) - (int(\$weight) - 30)) != 0 ) {
( (\$weight - int(\$weight)) < 0.5 ) ? \$half_kilos += 1 : \$half_kilos += 2;
print "\$half_kilos\n";
}

I expect \$half_kilos to be 21. Failing that, 22. But I get 23!

There's probably something really simple here I've not spotted, can
someone please enlighten me? I admit that my example would be clearer
written as a regular 'if...then...else', but I'd only just remembered
these and had used one (in a simpler form), and wanted to drum it in, so
used it again... I can remember how they work now... but can't get this
one to work.

Justin.

--
Justin C, by the sea.

Re: if .. then .. else shorthand problem

Justin C wrote:

Maybe this will show the issue more clearly.
my \$weight = 40.18;

my \$half_kilos = (( int(\$weight) -30 ) * 2);
print "\$half_kilos\n";
if ( ((\$weight - 30) - (int(\$weight) - 30)) != 0 ) {
( (\$weight - int(\$weight)) < 0.5 )
? \$half_kilos .= 'a'
: \$half_kilos .= 'b';
print "\$half_kilos\n";
}
20
20ab

Solutions:

\$half_kilos += ( (\$weight - int(\$weight)) < 0.5 ) ? 1 : 2;

or

( (\$weight - int(\$weight)) < 0.5 )
? ( \$half_kilos += 1 )
: ( \$half_kilos += 2 );

Re: if .. then .. else shorthand problem

J. Gleixner wrote:

But it doesn't show what the problem was, whereas looking at the perlop
page does:

=====
Because this operator produces an assignable result, using assignments
without parentheses will get you in trouble.  For example, this:

\$a % 2 ? \$a += 10 : \$a += 2

Really means this:

((\$a % 2) ? (\$a += 10) : \$a) += 2

Rather than this:

(\$a % 2) ? (\$a += 10) : (\$a += 2)

That should probably be written more simply as:

\$a += (\$a % 2) ? 10 : 2;

=====

and "\$half_kilos .= 'a'" is an assignment.

--
Just because I've written it doesn't mean that
either you or I have to believe it.

Re: if .. then .. else shorthand problem

Ew :-)

Another post indicated the parsing pitfall of putting
assignment in the ?: operator sequence.  Better to keep ?:
limited to just evaluation as "perldoc perlop" suggests.

hth
t

Re: if .. then .. else shorthand problem

OK, I see the error of my ways. The bottom line, I think, to get the
result you expect, is to always use parens for that type of statement.

Thanks to B&B, JG, and Tony for the help.

Justin.

--
Justin C, by the sea.

Re: if .. then .. else shorthand problem

JC> OK, I see the error of my ways. The bottom line, I think, to get the
JC> result you expect, is to always use parens for that type of statement.

nope. the bottom line is that you shouldn't do side effects with ?:. its
purpose is to return a value selected by a boolean test. the key word is
'return'. since perl allows side effects in expressions you are allowed
to put them inside ?: but it is very bad practice even if you use
parens. it is bypassing the purpose of the operator. if you want side
effects based upon a boolean, use if/else statements.

uri

--
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
--------- Free Perl Training --- http://perlhunter.com/college.html ---------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------

Re: if .. then .. else shorthand problem

JC> I've only just started using the shorthand for the "if .. then .. else"
JC> statement: (test) ? this : or_that;

JC> Here's what I have:

JC> use strict;
JC> use warnings;

JC> my \$weight = 40.18;

JC> my \$half_kilos = (( int(\$weight) -30 ) * 2);
JC> print "\$half_kilos\n";
JC> if ( ((\$weight - 30) - (int(\$weight) - 30)) != 0 ) {
JC>     ( (\$weight - int(\$weight)) < 0.5 ) ? \$half_kilos += 1 : \$half_kilos += 2;
JC>     print "\$half_kilos\n";
JC> }

JC> I expect \$half_kilos to be 21. Failing that, 22. But I get 23!

JC> There's probably something really simple here I've not spotted, can
JC> someone please enlighten me? I admit that my example would be clearer
JC> written as a regular 'if...then...else', but I'd only just remembered
JC> these and had used one (in a simpler form), and wanted to drum it in, so
JC> used it again... I can remember how they work now... but can't get this
JC> one to work.

I think you need to look at rounding and try to formulate the
calculation in general math terms, not if-then-else statements.  What
you're doing above is like using a rock to open the window.

Ted

Re: if .. then .. else shorthand problem

Don't confuse expressions with statements. The ternary ? : operator is not
a statement.

That evaluates both "\$half_kilos += 1" and "\$half_kilos += 2", then
selects the appropriate value. What you need to do is to use the ternary
operator with operands that have no side effects, as in the code suggested
by J. Gleixner.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT  <http://patriot.net/~shmuel

Unsolicited bulk E-mail subject to legal action.  I reserve the
right to publicly post or ridicule any abusive E-mail.  Reply to
domain Patriot dot net user shmuel+news to contact me.  Do not

Re: if .. then .. else shorthand problem

Not in Perl you don't:

~% perl -le'
\$x = 1;
(\$x == 1) ? (\$x += 1) : (\$x += 2);
print \$x'
2
~%

You do need to get your precedence correct, however:

~% perl -MO=Deparse,-p -e'(\$x == 1) ? \$x += 1 : \$x += 2'
(((\$x == 1) ? (\$x += 1) : \$x) += 2);
-e syntax OK
~%

(the (\$x == 1) in both cases is to defeat the optimizer).

It is, however, generally considered bad style to use a ?: operator in
void context (that is, when you're ignoring the return value). I've
sometimes wondered how hard it would be to add an 'else' low-precedence
logical operator, so you could write

\$x == 1
and \$x += 1
else \$x += 2;

Ben