Perl Weak Typing Woes

Recently the following block of code was brought up by a colleague at work, anyone familiar with Perl (or other languages with similar automatic type coercion) will immediately spot how the guarding if statement works. A zero value will cause the if condition to fail, thus avoiding a division by zero exception.

if ($middle) {
    $result = (($start / $middle) * 100) - 100;
}

It was quite a surprise when during testing, the following exception was raised. How can the division get executed when the value of $middle is zero?

Illegal division by zero at Module.pm line 2.

To understand why we need to think about all of the different possible values which Perl coerces to zero, starting with the obvious 0, ‘0’ (the string), and also the more obscure undef, ‘0.0’, etc …

A little Perl knowledge tells us that 0 is falsy, so our guard would work, as are ‘0’ (the string) and undef. But that isn’t the case with the string ‘0.0’.

if ('0.0') {
    print 'Truthy';
} else {
    print 'Falsy';
}

This was confirmed through tracing the source of the data through the code, and indeed the value of $middle was being set to the string ‘0.0’.

The simple fix was to explictly cast to an integer, before the implicit boolean coercion in the if statement.

if (int $middle) {
    $result = (($start / $middle) * 100) - 100;
}

Fancy reading more? See more blog posts.