Perl Weekly Challenge 031: Division by Zero & Dynamic Variable Name

Division by zero

Create a function to check divide by zero error without checking if the denominator is zero.

Perl already checks the denominator when dividing. All we need to do is to catch the exception it throws and check it instead of checking the value of the denominator.

The following division subroutine uses Try::Tiny to catch the exception. It’s a good practice not to use the low level eval, see for example Bug in eval in pre-5.14 for the reasons.

#!/usr/bin/perl
use warnings;
use strict;

use Try::Tiny;

sub division {
    my ($numerator, $denominator) = @_;
    try {
        { safe => 1, result => $numerator / $denominator }
    } catch {
        { safe => 0, error => $_ }
    }
}

use Test::More tests => 4;

ok division(1,2)->{safe};
ok !division(1,0)->{safe};

is division(1,2)->{result}, 1/2;
like division(1,0)->{error}, qr/Illegal division by zero/;

The subroutine returns a hash reference, the hash’s safe key tells us whether it’s safe to run the division; the result key contains the result if it is safe; and the error contains the exception text otherwise.

Dynamic variable name

Create a script to demonstrate creating dynamic variable name, assign a value to the variable and finally print the variable. The variable name would be passed as command line argument.

Let’s start with a warning:

Never use an external string as a variable name!

Here are links to the three famous articles on the subject by Mark Jason Dominus from 1998 and 1999:

In order to use the symbolic reference (that’s how storing a variable’s name in a variable is called), we have to turn strict 'refs' off. We are entering the wilderness.

The task is now pretty easy. We just use the syntax we normally use for hard references:

#!/usr/bin/perl
use warnings;
use strict;

my $var_name = shift;
{   no strict 'refs';
    ${ $var_name } = "Don't try this at home!";
    print "\$$var_name: ", $$var_name, "\n";
}

Running the script like pwc031-2.pl fred outputs the expected

$fred: Don't try this at home!

To see how the code can break in a hard-to-debug way, try using some less common variable names:

$ ./pwc031-2.pl '?'
Argument "Don't try this at home!" isn't numeric in scalar assignment at ./pwc031-2.pl line 7.
$?: 0

$ ./pwc031-2.pl +
Modification of a read-only value attempted at ./pwc031-2.pl line 7.
[255]

$ ./pwc031-2.pl \\
$\: Don't try this at home!
Don't try this at home!$ # ← yes, the prompt starts right here without a newline.
$ ./pwc031-2.pl ,
$,: Don't try this at home!Don't try this at home!Don't try this at home!

I’ve encountered symbolic reference in a production code at $job - 1. You can read about this in my meditation Can you use string as a HASH ref while “strict refs” in use?— it also contains a challenge to implement the weird behaviour under strict 'refs'. Don’t reveal the solution before trying it yourself!

Leave a comment

About E. Choroba

user-pic I blog about Perl.