Hi, Suppose I'm writing a file browser, with a pane on the left to display the filesystem hierarchy, and a frame on the right to preview the file.
Suppose I have a convenience function, preview_file which takes a
path and returns a value that the frame display view knows to
render.
Let's define this for HTML files, where the desired preview is a
summary of the text:
use Text::Summarize;
use HTML::ToAscii;
multi sub preview_file ($filename where /\.html$/ ) {
my $handle = open($filename, :r); # might fail if $filename is
unreadable
return summarize(html2ascii(=$handle)); # might fail if HTML is
invalid
}
And this code is called when the user clicks on a file in the pane:
class NiftyUI {
use fatal;
method handl_some_click ($file) {
$.right_frame.display(preview_file($file.name));
}
method handle_event ($event) {
$?SELF.dispatch_event($event);
CATCH {
when NiftyBackend::Exception {
$?SELF.display_error_box($!);
}
default { die $! };
}
}
}
With the current shape of the code if any of the possible failures
in the backend code happen, they are reported in a message dialog.
Now, let's say we would like to add a feature, that lets the user
change the mode of the file if it's unreadable.
Several approaches to doing this:
* give the backend an abstract object, a Frontend of sorts:
$frontend.ask_user("do you want to make the file readable?")
* throw internal exceptions, and let the frontend handle the
exception and retry the action:
method handle_some_click ($file) {
$.right_frame.display(preview_file($file.name));
CATCH {
when IO::Errors::PERMISSION_DENIED {
if ($?SELF.ask_user_to_chmod_file($file)) {
make_readable($file);
$?SELF.handle_some_click($file); #
retry the event
} else { die $! }
}
}
}
I propose a new model - each exception has a continuation that
allows it to be unfatalized.
The exception object has info on whether the fatality of the
exception was due to a die, or a use fatal, and lets the exception
handler decide accordingly.
Then we have code that looks like this:
method handle_some_click ($file) {
$.right_frame.display(preview_file($file.name));
CATCH {
when IO::Errors::PERMISSION_DENIED {
if ($?SELF.ask_user_to_chmod_file($file)) {
make_readable($file);
$!.continue(open($file, :r)); # the
return value of the failed open is
# overridden by the return value of
this (hopefully successful) open.
} else { die $! }
}
when HTML::ToAscii::Exception { # badly formed
$!.continue("The HTML file contained a syntax
error");
# this string is passed to summarize instead of
the undef exception object
}
}
}
The value this has is in handler cascading... If, for example,
make_readdable($file) failed too, then an exception handler around
handle_some_click could handle display a sudo box, to try it again,
and eventually continue back into the make_readable($file) call,
which will then continue into the failed open.
--
() Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418 perl hacker &
/\ kung foo master: /me tips over a cow: neeyah!!!!!!!!!!!!!!!!!!!!!!
pgprazW7gmwVh.pgp
Description: PGP signature
