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!!!!!!!!!!!!!!!!!!!!!!

Attachment: pgprazW7gmwVh.pgp
Description: PGP signature

Reply via email to