Search code examples
perloperator-precedenceconditional-operator

Perl ternary conditional operator


I'm trying to write more efficient code in my scripts and have been implementing ternary conditional operators on occasion. I can't understand why I am getting an additional result when using a ternary conditional operator in a loop:

#!/usr/bin/perl

use strict;
use warnings;

my @array = ('Serial = "123"', 'Serial = "456"', 'Serial = "789"');
my ($test1,$test2);
foreach my $a (@array){
        !$test1 ? $test1 = $a  : $test1 .= " AND " . $a;
}
foreach my $b (@array){
        if (!$test2) {
                $test2 = $b
        } else {
                $test2 .= " AND " . $b;
        }
}
print "Test1: $test1\n";
print "Test2: $test2\n";

Output:

~/bin/test.pl
Test1: Serial = "123" AND Serial = "123" AND Serial = "456" AND Serial = "789"
Test2: Serial = "123" AND Serial = "456" AND Serial = "789"

Test1 output has an additional "Serial = "123", What am I doing wrong?


Solution

  • Assignment has lower precendence than ?. This

    !$test1 ? $test1 = $a  : $test1 .= " AND " . $a;
    

    is equivalent to this:

    (!$test1 ? $test1 = $a  : $test1) .= " AND " . $a;
    

    So first $test1 will become Serial = "123" and then AND Serial = "123" gets appended immediately after.

    Try this:

    !$test1 ? ($test1 = $a)  : ($test1 .= " AND " . $a);
    

    A better solution would be this:

    $test1 = !$test1 ? $a  : $test1 . " AND " . $a;
    

    Using the ternary operator for side effects can get quite messy and I'd recommend to avoid it.

    Edit

    As noted by MuIsTooShort join(' AND ', array) would be the most concise and readable solution in your case.