Search code examples
perlbooleantype-conversion

Why is "!!" considered bad form in Perl?


During a recent job interview process, I submitted some sample Perl code which used the so-called "secret" !! operator. Later, when discussing the code, one of the interviewers asked me why I chose to use that, and indicated that it was considered bad form. He didn't elaborate as to why.

My team and I have been using this operator for years, without ever realizing it was considered "bad form."

Does the "bang bang" operator have side-effects or other unexpected behavior? Why is it, or might it be, considered "bad form" by some? Is there an idiomatic alternative?

Below are a few examples where I would have considered !! acceptable and/or desirable.

  1. The actual code in the coding exercise, which is an example of adding booleans:

    while (my $line = <$F>) {
        # snip
        exists $counts{lines} and $counts{lines} += !! chomp $line;
    }
    
  2. Using a boolean value as a hash key (clearly a simplified example):

    sub foo {
        my ($input) = @_;
        my %responses = ( '' => "False", 1 => "True" );
        return $responses{ !! $input };
    }
    
  3. Using a boolean in a bitwise operation, or even pack():

    sub foo {
        my ( $a, $b, $c ) = @_;
        my $result = !!$a + (!! $b)<<1 + (!! $c)<<2;
        return $result;
    }
    
  4. You need to do a typecast for use by an external library/process, such as a database, which only considers certain values to be truthy:

    my $sth = $dbh->prepare("INSERT INTO table (flag,value) VALUES (?,?)")
    $sth->execute("i_haz_cheeseburger", !! $cheeseburger_string)
    

Solution

  • Your !! takes advantage of two obscure things in Perl: The specific values that ! returns, and that one of the possible values is dualvar (a scalar containing both a string and a number). Using !! to compound these behaviors is admittedly pithy. While its pithiness can be a huge plus, it can also be a rather big minus. Don't use features that result in a project mandating that "the use of Perl is forbidden on this project."

    There are lots of alternatives to $count += !! (some_expression) to count occurrences of truthy values of that expression. One is the ternary, $count += (some_expression) ? 1 : 0. That too is a bit obscure. There is a nice compact way to do what you want, which is to use the post-if:

    $x++ if some_expression;
    

    This says exactly what you are doing.