Perl Weekly Challenge: Week 31

Week 31 Challenge 1:

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

To do this we need a way to capture a runtime error or exception. Most modern programming languages have structured exception handling now. Perl is no exception (Haha! See what I did there?) Perl5 has modules that mimic the try...catch syntax you see in e.g. C++ or Java but it's inbuilt method is slightly different. It uses the eval() function which runs a piece of Perl code in its own sandboxed environment, trapping the kinds of errors such as division by zero which normally will crash a program. The only problem is getting the specific error (which we might want to do if we want to handle several exceptions in different ways.) requires parsing the actual output of the variable $@ or $EVAL_ERROR if you use English as I always do for clarities sake.

sub isDividedByZero {
    my ($numerator, $denominator) = @_;

    eval { $_ = $numerator / $denominator; };

    if ($EVAL_ERROR =~ /division by zero/ms) {
        return 1;
    }

    return undef;
}

(Full code on Github.)

Raku has special syntax for this purpose. The easiest way to catch an exception is in an aptly named CATCH block. I was unable to find out what is the equivalent of $EVAL_ERROR so I just caught all exceptions (i.e. default).

sub isDividedByZero($numerator, $denominator) {
    ($numerator / $denominator).grep({});

    CATCH {
        default {
            return True;
        }
    }

    return False;
}

(Full code on Github.)

A curious thing to note is that exceptions are only fired if the code actually "does" something. It is not enough to just assign the value of the division to a variable as I did in Perl5. The first solution that came to mind was to .say() the result. But that would have the side-effect of printing the result if no exception was fired. So instead I grepped for nothing.

Week 30 Challenge 2:

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.

We can solve this by creating a scalar containing a reference to the variable name like this:

$$ARGV[0] = 42;

say "$ARGV[0] = $$ARGV[0]";

(Full code on Github.)

In Raku I think this is how you achieve the same result but I'm not entirely sure.

sub MAIN( Str $var ) {
    my $newvar = $var;
    $($newvar) = 42;

    say "$var = ", $($newvar);
}

(Full code on Github.)

$var has to be copied to $newvar because Strs are immutable by default. Again, I'm not entirely sure why that should be a problem but evidently it is.