Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Confused by Perl ternary operator

by newest_newbie (Acolyte)
on Aug 23, 2004 at 19:10 UTC ( [id://385184]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,
My understanding of the ternary operator is (test) ? <do if true> : <do if false>

But in the code below I am not convinced the way it is working. Infact, it is working like (test) ? <do if false> : <do if true>

Monks, please bear with my ignorance...

my $fname = "My First Name"; my $mname = "My Middle Name"; my $lname = "My Last Name"; &tst_array1 ($fname, $mname, $lname); &tst_array2 ($fname, $mname, $lname); &tst_array3 ($fname, $mname, $lname); sub tst_array1 { my ($param1, $param2, $param3); $param1 = shift; @_ ? $param2 = "Shift" : $param2 = shift; @_ ? $param3 = "Shift" : $param3 = shift; print "In tst_array1:\n$param1, $param2, $param3\n"; } sub tst_array2 { my ($param1, $param2, $param3); $param1 = shift; @_ ? $param2 = shift : $param2 = "Shift"; @_ ? $param3 = shift : $param3 = "Shift"; print "In tst_array2:\n$param1, $param2, $param3\n"; } sub tst_array3 { $param1 = shift; print "\@_ = @_: \$param1 = $param1\n"; $param2 = shift; print "\@_ = @_: \$param2 = $param2\n"; $param3 = shift; print "\@_ = @_: \$param3 = $param3\n"; print "In tst_array3:\n$param1, $param2, $param3\n"; }
The result:
In tst_array1:
My First Name, My Middle Name, My Last Name
In tst_array2:
My First Name, Shift, Shift @_ = My Middle Name My Last Name: $param1 = My First Name @_ = My Last Name: $param2 = My Middle Name @_ = : $param3 = My Last Name
In tst_array3:
My First Name, My Middle Name, My Last Name

janitored by ybiC: Moved <code> tags such that they're only around codeblocks, and balanced <readmore> tags also. Retitled from "Perl Ternary operator" as per consideration

Replies are listed 'Best First'.
Re: Confused by Perl ternary operator
by fruiture (Curate) on Aug 23, 2004 at 19:25 UTC

    Operator Precedence, again.

    A ? B = C : D = E # resolves ( A ? ( B = C ) : D ) = E

    So, no matter what A evaluates to, E is being assigned, either to "B = C" (which is the same as assigning to B) or D. In your case B and D are identical, so your ?: operator doesn't do anything useful. Solution:

    @_ ? ( $param2 = shift ) : ( $param2 = "Shift" ); # and while we're at it, of course, refactor that $param2 = @_ ? shift : "Shift"

    The last line demonstrates why the precedence of "?:" vs. "=" is actually sensible. HTH

    --
    http://fruiture.de
Re: Confused by Perl ternary operator
by Roy Johnson (Monsignor) on Aug 23, 2004 at 19:19 UTC
    You should be writing
    $param2 = @_ ? 'Shift' : shift;
    instead of
    @_ ? $param2 = 'Shift' : $param2 = shift;
    But if you want to do what you're doing, you need some parentheses.
    @_ ? $param3 = "Shift" : ($param3 = shift);
    I don't know what the parsing problem is, exactly, but no doubt someone else has already posted it while I've been composing this. :)

    Caution: Contents may have been coded under pressure.

      In this case, for arcane reasons, $param3 = @_ ? "Shift" : shift works as-is but is execution-order unsafe and if the expression were included in some other larger expression, could be quite a problem.

      $param3 = @_ ? "Shift" : $_[0]; shift;

      The preceding example would be the safe way to write it.

        How is that execution-order unsafe? ?:'s first operand has to be evaluated before either the second or third.

        After writing the above, I checked perlop.pod, and technically you are correct. ?: isn't documented as short-circuiting, so perl potentially could evaluate the 2nd and 3rd operands before testing the first one. However, I believe that it is intended to short-circuit and will submit a patch to the doc.

        As an interesting side note, structures with else or elsif are implemented using condexpr (the ?: operator). That is,

        if (foo) { bar } else { baz }
        is identical to
        foo ? do { bar } : do { baz }
        so the short-circuiting of ?: is pretty guaranteed.
      C:>perl -MO=Deparse,-p -e"@_ ? $param2 = 'Shift' : $param2 = shift;" ((@_ ? ($param2 = 'Shift') : $param2) = shift(@ARGV)); -e syntax OK ( ( @_ ? ( $param2 = 'Shift') : $param2 ) = shift(@ARGV) );
Re: Confused by Perl ternary operator
by hardburn (Abbot) on Aug 23, 2004 at 19:30 UTC

    Someone with more knowledge of internals will have to confirm, but I bet that the assignment is being processed before the conditional. As a result, the evaluation goes from left to right, thus making the last assignment (the one in the "false" portion) be the one that sticks.

    The ternary operator gets its power from being able to embed it as part of a larger statment, not just in using it as an obscure if statement. Here's a better way to write that code:

    $param2 = @_ ? "Shift" : shift;

    The ternary operator will return the value passed from whichever argument was run. You want to avoid side-effects in these arguments.

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: Confused by Perl ternary operator
by Nkuvu (Priest) on Aug 24, 2004 at 00:41 UTC
    I've seen some references to this in the preceding comments, but nothing that's jumping out and saying "Er..." so I'll say it.

    When you say you're thinking that the ternary operator functions like (test) ? true : false you are correct. But what I see is a possible problem with your test...

    Er. Never mind me, I'm waiting for dinner to finish, and I'm starving, and so I completely misread the code. That's my story, and I'm sticking to it.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://385184]
Approved by dragonchild
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (6)
As of 2024-04-19 15:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found