I remember a brief time in the mid-​2000s insisting on so-​called Yoda conditions” in my Perl. I would place constants to the left of equality comparisons. In case I accidentally typed a single = instead of ==, the compiler would catch it instead of blithely assigning a variable. E.g.:

if ( $foo == 42 ) { ... } # don’t do this
if ( 42 == $foo ) { ... } # do this
if ( $foo = 42  ) { ... } # to prevent this

And because a foolish consistency is the hobgoblin of little minds, I would even extend this to string and relational comparisons.

if ( 'bar' eq $foo ) { ... } # weirdo
if ( 42 > $foo )     { ... } # make it stop

It looks weird, and it turns out it’s unnecessary as long as you precede your code with use warnings;. Perl will then warn you: Found = in conditional, should be ==“. (Sidenote: Perl v5.36, due in mid-​2022, is slated to enable warnings by default if you do use v5.35; or above, in addition to the strictness that was enabled with use v5.11;. Yay for less boilerplate!)

If you want to fatally catch this and many other warnings, use the strictures module from CPAN in your code like this:

use strictures 2;

This will cause your code to throw an exception if it commits many categories of mistakes. If you’re running in a version control system’s working directory (specifically Git, Subversion, Mercurial, or Bazaar), the module also prevents you from using indirect object syntax, Perl 4‑style multidimensional arrays, and bareword filehandles.

Getting back to assignments vs. conditionals, there is one case where I’ve found it to be acceptable to use an assignment inside an if statement, and that’s when I need to use the result of a check inside the condition. For example:

if ( my $foo = some_truthy_function() ) {
    ... # do something further with $foo
}

This keeps the scope of some_truthy_function()s result inside the block so that I don’t pollute the outer scope with a temporary variable. Fortunately, Perl doesn’t warn on this syntax.

5 thoughts on “Avoid Yoda conditions in Perl you should

Comments are closed.