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!!!!!!!!!!!!!!!!!!!!!!
pgpYDj9q8BwQt.pgp
Description: PGP signature