Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

ternary operator

by pglenski (Beadle)
on Jul 17, 2006 at 22:10 UTC ( [id://561870]=perlquestion: print w/replies, xml ) Need Help??

pglenski has asked for the wisdom of the Perl Monks concerning the following question:

The trinary operator looks to be very simple yet sometimes it just doesn't work the way I would think. Take this code snippet. It always set it to 'c' no matter what is typed. Any ideas?
print "Field 1 & 2 Separate or Combined? "; chomp($_=<STDIN>); lc($_); # always sets $OPER to 'c' $_ eq 's' ? $OPER='s' : $OPER='c'; # but this works as expected: $OPER='s' if ($_ eq 's'); $OPER='c' if ($_ eq 'c');

2006-07-18 Retitled by Steve_p, as per Monastery guidelines
Original title: 'trinary operator'

Replies are listed 'Best First'.
Re: ternary operator
by bobf (Monsignor) on Jul 17, 2006 at 22:26 UTC

    The previous two posts show how to use the ternary operator to assign a value to a variable, but neither mentioned that your lc statement wasn't working as you intend. The lc function will use $_ as an argument if none is provided, but it returns the lowercased string. Since you never assign the return value to anything, it gets ignored (this would have been evident if you used warnings). To fix it, reassign to $_:

    print "[$_]\n"; # S lc( $_ ); # warning: "Useless use of lc in void context" print "[$_]\n"; # S $_ = lc( $_ ); print "[$_]\n"; # s

Re: ternary operator
by Hue-Bond (Priest) on Jul 17, 2006 at 22:28 UTC
      $_ eq 's' ? $OPER='s' : $OPER='c';

    That's a priority issue. Try:

    $_ eq 's' ? ($OPER='s') : ($OPER='c');

    However, your code has a worse problem: mo strict nor warnings. As a consequence, your usage of lc is useless without you noticing it:

    print "Field 1 & 2 Separate or Combined? "; chomp($_=<STDIN>); lc($_); $_ eq 's' ? $OPER='s' : $OPER='c'; print "OPER $OPER\n"; __END__ Field 1 & 2 Separate or Combined? S OPER c

    Try this fixed version:

    use strict; use warnings; print "Field 1 & 2 Separate or Combined? "; chomp ($_ = <STDIN>); my $OPER = lc eq 's' ? 's' : 'c'; print "OPER $OPER\n";

    --
    David Serrano

Re: ternary operator
by rhesa (Vicar) on Jul 17, 2006 at 22:15 UTC
    You could try
    $OPER = $_ eq 's' ? 's' : 'c' ;
Re: ternary operator
by crashtest (Curate) on Jul 17, 2006 at 23:51 UTC

    This turned into an interesting thread. One quibble: it's called the ternary operator, not the trinary operator.

Re: ternary operator
by johngg (Canon) on Jul 17, 2006 at 22:18 UTC
    Try

    $OPER = $_ eq 's' ? 's' : 'c';

    Cheers,

    JohnGG

Re: ternary operator
by GrandFather (Saint) on Jul 17, 2006 at 22:36 UTC

    There may be a Perl bug here. Because of operator precedence I'd have expected that the trinary experession shouldn't compile. The assignment operator has lower percedence than the trinary operator.

    However the immediate answer to your problem is to fix the precedence issue. Here are two fixes:

    1/ $test ne 'c' ? ($OPER='s') : ($OPER='c'); 2/ $OPER = $test ne 'c' ? 's' : 'c';

    DWIM is Perl's answer to Gödel
      No bug. The statement parses as ($test ne 'c' ? ($OPER = 's') : $OPER) = 'c';

      Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
      How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart

        which to me looks like:

        $OPER = 's' = 'c';

        when $test ne 'c' is true. And that should fail with a "Can't modify constant item in scalar assignment" error. However no errors and no warnings are generated for either condition.

        Using ?: to select a variable to be assigned to I'm happy with:

        test ? $p1 : $p2 = value;

        but the half assignement variant implied by the precedence (and made explicit by the brackets shown in your reply) is just bizare.


        DWIM is Perl's answer to Gödel
Re: ternary operator
by Moron (Curate) on Jul 18, 2006 at 09:32 UTC
    The real cause of the problem is that the '=' operator is being allowed to execute from left to right in a way that disrupts the ternary operator. Putting brackets around each of the three arguments to the ternary operator forces the correct precedence (although still abusing the operator).
    ( $_ eq 's' ) ? ( $OPER = 's' ) : ( $OPER = 'c' ); # still cringeing
    It is more normal to use these arguments to return the conditional values to an assignment rather than assign values inside the arguments, i.e. this would be a more normal way:
    # </cringe> $OPER = ( $_ eq 's' ) ? 's' : 'c';

    -M

    Free your mind

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://561870]
Approved by Hue-Bond
Front-paged by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2024-04-23 23:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found