Raku exceptions: why are errors thrown sometime after the code that caused the errors?

161 Views Asked by At

This seems crazy to me:

use v6.d;

say "Before division by zero!";
my $result = divide(3, 0);
say "After division by zero!";

sub divide($a, $b) {
    my $result;
    $result = $a / $b;  # Line 11
    return $result;
}

sub go($x) {
    say "hello";
    say $x;             # Line 17
}

go($result);            # Line 20

--output:--
Before division by zero!
After division by zero!
hello
Attempt to divide by zero when coercing Rational to Str
  in sub go at b.raku line 17
  in block <unit> at b.raku line 20

The error says to look at line 17. Yet, the error is from line 11.

In perl:

use strict;
use warnings;
use feature qw{say};
use Data::Dumper;


say "Before division by zero!";
my $result = divide(3, 0);
say "After division by zero!";

sub divide {
    my ($a, $b) = @_; 
    my $result = $a / $b;    # Line 13
    return $result;
}

sub go {
    my ($x) = @_;
    say "hello";
    say $x;
}

go(20, 30);

--output:--
Before division by zero!
Illegal division by zero at a.pl line 13.

The perl program produces an error that points to the code that actually caused the error.

Furthermore, in raku you can't even use a try block to contain the error:

sub divide($a, $b) {
    my $result;

    try {
        $result = $a / $b; 
    }

    return $result;
}

That produces the same output as the raku program above.

Why did raku decide that:

When dealing with an exception, the place where the exception is "used" determines when it's thrown.

...where "used" seems to mean output with say()? As you can see from my example, it makes it difficult to figure out where the error is in your code. Does that have to do with lazy evaluation?

1

There are 1 best solutions below

3
librasteve On

This question reiterates this example from a popular "Raku by Example" course. That course explains the situation like this:

These last two code snippets illustrate the mechanism of failing softly allowed by Raku. In short, this means that exceptions aren't thrown until the value associated with them is about to be used. And this is what happens in these code snippets; the exceptions are only thrown when the value from divide(3,0) is used.

This reference is not provided accurately or in context.

The last part of the question asks of this statement "why did Raku decide that"... but the original reference already answers this.