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;
}
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;
}
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]";
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);
}
$var
has to be copied to $newvar
because Str
s are immutable by default. Again, I'm not entirely sure why that should be a problem but evidently it is.