http://qs1969.pair.com?node_id=586664

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

Hi Monkees,

Why does the following code print 10 bars for the first section, yet behaves as I expected for the second?

#Huh? 10 bars, WTF? for(1..10){ $_>5 ? $x='foo' : $x='bar'; print "$_:$x\n"; } # That's better - 5 foos and 5 bars for(1..10){ $x=($_>5 ? 'foo' : 'bar'); print "$_:$x\n"; }
Tom Melly, tom@tomandlu.co.uk

Replies are listed 'Best First'.
Re: Conditional Operator Confusion
by davorg (Chancellor) on Nov 29, 2006 at 12:14 UTC

    Looks like it's operator precendence. This works as you expected.

    for(1..10){ $_>5 ? ($x='foo') : ($x='bar'); print "$_:$x\n"; }
    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      Well, pfft - that's no good for golf... although I'm still confused - how does precedence work in this context?

      Tom Melly, pm@tomandlu.co.uk
        ??
        C:\>perl -MO=Deparse,-p for(1..10){ $_>5 ? $x='foo' : $x='bar'; print "$_:$x\n"; } ^Z foreach $_ (1 .. 10) { ((($_ > 5) ? ($x = 'foo') : $x) = 'bar'); print("${_}:$x\n"); } - syntax OK
Re: Conditional Operator Confusion
by GrandFather (Saint) on Nov 29, 2006 at 12:47 UTC

    You may like:

    for(1..10){ $x= $_ > 5 && 'foo' || 'bar'; print "$_:$x\n"; }

    instead. Update: You may like:

    print"$_:${[$_>5&&'foo'||'bar']}[0]\n"for 1..10;

    even better.


    DWIM is Perl's answer to Gödel
Re: Conditional Operator Confusion
by MonkE (Hermit) on Nov 29, 2006 at 13:59 UTC
    To understand how precedence works in this circumstance, consider the following variation of the OP's code. The assignment operator has enough precendence to end evaluation of the trinary conditional operator, so the conditional operator is simply choosing an "lvalue" for the assignment operator. The parenthesis in the second loop help show what's actually happening.
    use strict; use warnings; my $x='baz'; my $y='moo'; for (1..10) { $_>5 ? $x='foo' : $y='bar'; print "x=$x, y=$y\n"; } # re-initialize vars print "----------\n"; $x = 'baz'; $y = 'moo'; # the above loop is functionally equivalent to: for (1..10) { ($_>5 ? $x : $y) = 'bar'; print "x=$x, y=$y\n"; }
    Output:
    x=baz, y=bar x=baz, y=bar x=baz, y=bar x=baz, y=bar x=baz, y=bar x=bar, y=bar x=bar, y=bar x=bar, y=bar x=bar, y=bar x=bar, y=bar ---------- x=baz, y=bar x=baz, y=bar x=baz, y=bar x=baz, y=bar x=baz, y=bar x=bar, y=bar x=bar, y=bar x=bar, y=bar x=bar, y=bar x=bar, y=bar
Re: Conditional Operator Confusion
by Herkum (Parson) on Nov 29, 2006 at 13:17 UTC
    Try this instead,
    for (1..10) { $x = $_ > 5 ? 'foo' : 'bar'; print "$_:$x\n"; }

    Ah, I just noticed that you had tried that in your second example. The real issue that you had was that you were trying to treat a trinary operator like an if-else statement. I have tried that before and it just don't work! :)

      Hey! The camel book told me it was just like an if-else (well, sort of). Hmm, I must admit that I'm still slightly in the dark here - none of the examples given so far help me understand exactly what is going on...

      map{$a=1-$_/10;map{$d=$a;$e=$b=$_/20-2;map{($d,$e)=(2*$d*$e+$a,$e** 2-$d**2+$b);$c=$d**2+$e**2>4?_:0}1..99;print$c}0..59;print$/}0..20;
      Tom Melly, pm@tomandlu.co.uk

        The trinary is much like any other operator, for example ==. Lets try this example,

        my $result = $a == $b

        Here, you get the result of the == operator, is $a equal $b. If they match it returns true, if they don't match it returns false.

        The trinary works in a similar manner except you are setting the value returned instead of the implied value of other operators.

        my $result = $a == $b ? 1 : 0;

        This does the same thing as the first example, except you are explicitly setting the value returned. Does this help?