develooper Front page | perl.beginners | Postings from April 2012

Re: Using the ternary operator to concat a string not working like Ithink?

Thread Previous | Thread Next
From:
Paul Johnson
Date:
April 4, 2012 01:38
Subject:
Re: Using the ternary operator to concat a string not working like Ithink?
Message ID:
20120404083846.GD22976@pjcj.net
On Tue, Apr 03, 2012 at 05:39:10PM -0400, Stan N/A wrote:
> I've run into a weird issue where the ternary operator isn't doing
> what I believe it normally would and need some help understanding the
> issue. I'm sure I'm missing some critical point, but perhaps this is
> an issue with perl. Here's a short 14 line script exemplifying the
> issue:
> 
> -----code-----
> #!/usr/bin/perl
> use strict;
> use warnings;
> 
> my %test = (
>     one => "first",
>     two => "second"
> );
> 
> $test{one} eq "first" ?
>     $test{one} .= " is the worst\n" :
>     $test{two} .= " is the best\n";
> 
> print $_ for values %test;
> ----code----
> 
> I believe the output should result with:
> 
> first is the worst
> second
> 
> The output I receive running this test is:
> 
> first is the worst
>  is the best
> second
> 
> This seems peculiar! Help!

Regardless of whether the ternary operator is "meant" to be used like
this, and aside from questions of style, it is useful to know what is
going on here and to be able to diagnose similar problems.

The problem you are seeing is due to precedence.  You can see from the
table in perlop that ?: has (slightly) higher precedence than .= and
this is what causes this behaviour.

You can check that by running:

 $ perl -MO=Deparse,-p -e '$test{one} eq "first" ? $test{one} .= " is the worst\n" : $test{two} .= " is the best\n"'
 ((($test{'one'} eq 'first') ? ($test{'one'} .= " is the worst\n") : $test{'two'}) .= " is the best\n");
 -e syntax OK

The -p option to Deparse tells perl to put in parentheses even when they
are not necessary, and in this case it explains the otherwise puzzling
behaviour you have seen.

The other bit of knowledge that might be required is that in Perl
assignment produces an lvalue (meaning you can assign to it).

Parenthetically, ?: also produces an lvalue if both its second and third
arguments are lvalues, which can be useful sometimes.

Most of this, including the specific problem you are seeing, is
documented in perlop under the heading "Conditional Operator".

-- 
Paul Johnson - paul@pjcj.net
http://www.pjcj.net

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About