Of fail, exceptions and catching

1 view
Skip to first unread message

Aaron Sherman

unread,
May 11, 2005, 7:44:28 AM5/11/05
to Perl6 Language List
Given:

"fail" with configurable behavior
"no fatal" to make "fail" just warn
"use fatal" to make "fail" throw exceptions

A question came up on #perl6 for the following code:

no fatal;
class Foo {
use fatal;
method bar() { fail; }
}
Foo.bar;

That is, bar() picks up a lexically scoped "use fatal", but the caller
of bar desires non-fatal behavior.

Possible results and reasons for them:

* Warning -- For this to work, I think you would need an implicit
CATCH block wrapper around each statement in a "no fatal"
section. This could be simulated by wrapping the entire no fatal
section in a continuation closure which is then called inside a
CATCH block which warns and re-invokes the continuation... if
continuations can be re-invoked after exceptions. That's an
interesting question on it's own actually.
* Fatal exception -- This implies that the callee's lexically
scoped fatal preference wins, which might be a reasonable thing
in concept, but seems to present no control to the user of a
module when the module author has specified a preference.
Perhaps that's a good thing. Perhaps it's bad. I do see a
problem with a program that uses several modules, all of which
have different opinions about fatality...
* Warning -- Another reason that you might get a warning would be
that there is some sort of dynamically scoped imposition of a
non-fatal context from "no fatal". That seems the least likely
to me, but I thought that I'd bring it up.

This came up when someone was considering writing a module, and was
saying that he really wanted "use fatal" as the default for his modules.
That seems like a reasonable thing to want, but I'm not sure how it
could be controlled correctly.

--
Aaron Sherman <a...@ajs.com>
Senior Systems Engineer and Toolsmith
"It's the sound of a satellite saying, 'get me down!'" -Shriekback


Juerd

unread,
May 11, 2005, 7:46:16 AM5/11/05
to Aaron Sherman, Perl6 Language List
Aaron Sherman skribis 2005-05-11 7:44 (-0400):

> "no fatal" to make "fail" just warn

I thought it wouldn't warn, but instead silently return undef (an
unthrown exception).


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

Luke Palmer

unread,
May 11, 2005, 9:46:41 AM5/11/05
to Aaron Sherman, Perl6 Language List
On 5/11/05, Aaron Sherman <a...@ajs.com> wrote:
> Given:
>
> "fail" with configurable behavior
> "no fatal" to make "fail" just warn

Juerd is right here, it doesn't warn. Instead of "die"ing, it returns
an undef with some helpful diagnostic information (an "unthrown
exception" as Larry has been calling it).

> "use fatal" to make "fail" throw exceptions
>
> A question came up on #perl6 for the following code:
>
> no fatal;
> class Foo {
> use fatal;
> method bar() { fail; }
> }
> Foo.bar;
>
> That is, bar() picks up a lexically scoped "use fatal"

No it doesn't. The fatal that refers to bar's return value belongs to
the caller of bar. Here's another example:

sub foo() {
fail;
}

use fatal;
sub bar() {
foo(); # foo() throws exception
}

no fatal;
sub baz() {
foo(); # foo() returns undef
}

use fatal;
bar(); # propagates exception from foo()
baz(); # turns baz()'s (from foo()'s) undef into an exception

no fatal;
bar(); # turns exception thrown from foo()'s into an undef
baz(); # returns the undef that it got from foo()

Does that clarify things? (I could tell there was some
misunderstanding going on, but I had a hard time explaining it.
Hopefully this example will clear things up)

Luke

Luke Palmer

unread,
May 11, 2005, 9:50:58 AM5/11/05
to Aaron Sherman, Perl6 Language List
On 5/11/05, Luke Palmer <lrpa...@gmail.com> wrote:
> sub foo() {
> fail;
> }
>
> use fatal;
> sub bar() {
> foo(); # foo() throws exception
> }
>
> no fatal;
> sub baz() {
> foo(); # foo() returns undef
> }
>
> use fatal;
> bar(); # propagates exception from foo()
> baz(); # turns baz()'s (from foo()'s) undef into an exception
>
> no fatal;
> bar(); # turns exception thrown from foo()'s into an undef
> baz(); # returns the undef that it got from foo()

Oh, just to avoid further confusion: In the baz() called under fatal,
it will only turn undefs that were generated by "fail" calls into
exceptions. Other sorts of undefs will be returned as ordinary
undefs.

Likewise, in the bar() called under no fatal, it will only turn
exceptions that were generated by "fail" calls into undefs. Other
sorts of exceptions stay as exceptions and propagate outward.

Luke

Aaron Sherman

unread,
May 11, 2005, 10:36:32 AM5/11/05
to Luke Palmer, Perl6 Language List
On Wed, 2005-05-11 at 09:50, Luke Palmer wrote:

> Oh, just to avoid further confusion: In the baz() called under fatal,
> it will only turn undefs that were generated by "fail" calls into
> exceptions. Other sorts of undefs will be returned as ordinary
> undefs.

Ok, so let me try to get my head around this:

fail is something like:

return undef but Exception(...some state info...);

the only question is whether the caller reacts to that special return
value like so:

if $return ~~ Exception {
return $return;
}

or simply ignores it. If you ignore the special return value, then you
presumably have the burden of coping with it in some other way, like so:

no fatal;
$socket.bind(:interface<localhost>, :port<80>) or
$socket.bind(*@defaults) or
die "Cannot bind: $!";

At the top-level (runtime), you would expect to have something like
(arm-waving some naming specifics):

given $program.(@args) {
when Exception { $*ERR.print $_.err; exit 1 }
default { exit +$_ }
}

Am I getting it now?

Reply all
Reply to author
Forward
0 new messages