On Sat, Oct 01, 2005 at 05:57:54 -0400, Austin Hastings wrote: > Internally, it may be the same. But with exceptions, it's implemented by > someone other than the victim, and leveraged by all. That's the kind of > abstraction I'm looking for. My problem with the whole notion of "Either > errorMessage resultingValue" in Haskell is that we _could_ implement it > in perl as "Exception|Somevalue" in millions of p6 function signatures. > But I don't _want_ to. I want to say "MyClass" and have the IO subsystem > throw the exception right over my head to the top-level caller.
In haskell it's the job of the Either monad to let you pretend you aren't doing Exception|Somevalue everywhere. You can sequence operations in a deeply nested manner, and then 'fail' at some point. Then control flow will just pop back up all the way with the error, instead of trying to continue. You don't really need to say 'Either ... ...', you just use do notation. > For appropriate definitions of both 'elegant' and 'convenient'. Java > calls this 'checked exceptions', and promises to remind you when you > forgot to type "throws Exception::Math::DivisionByZero" in one of a > hundred places. I call it using a word to mean its own opposite: having > been exposed to roles and aspects, having to code for the same things in > many different places no longer strikes me as elegant or convenient. I agree with that wholeheartedly, but in haskell you are making no obligation towards the shape of an exception - it can be 'Either thing Error' where Error is any data type you like. In this sense haskell is just as flexible but requires more abstraction than perl etc. It has it's merits - it's safer, and more reusable. It tends to win ICFP contests, and so forth. However, to just get that thing working real fast, without having to pay too much when the context becomes maintenance instead of development, i think Perl 6 will be the most suitable language in the world. > Right. At some level, you're going to have to do that. This to me is > where the "err" suggestion fits the most comfortably: "err" (or "doh!" > :) is a keyword aimed at ad-hoc fixes to problems. It smooths away the > horrid boilerplate needed for using exceptions on a specific basis. Which is why it's such a nice propsal =) > As syntactic sugar goes, it's not powerful enough yet. err next # catch all err Pattern, next # catch some Putting my code where my mouth is: sub infix:<err> (&lhs is delayed, Pattern ?$match = Any, &rhs is delayed) { lhs; CATCH { when $match { rhs } default { die } } } Ofcourse, these can also stack: my $fh = open "file err rx/Permission Denied/, next err rx/No such file/, die; But i don't think this is very useful for one or at the very most two catches - for anything else it's ad-hoc nature just doesn't scale as nicely as CATCH blocks, which can be applied to several error generating blocks of code at once. Ofcourse, true acid heads can always say: do { ...; ...; } err ..., ... err ..., ...; but that's their problem. =) > The last sentence is telling, I think. The run-time system SHOULD take > as much care as possible. And rub my feet. Yes =) > True for any method that invokes exit(), no? Or that says NEXT on a > label outside its scope. Well, that's a semantic detail. The issue is that those methods *can* return, but don't. A continuation will never return - because it already has another place to return - the place that created it. This is ignoring CPS, ofcourse, in which every return and every call is a continuation. While this may be true under the hood, this is not what the average Perl 6 user can observe. > The scenario is that I try something (error_throwing_code) and catch an > exception. Then while showing a dialog box to the user, for example, I > get another exception: not enough handles or whatever. So someone higher > than me resolves that on my behalf, then resumes me. I'm still trying to > resume the error thrown earlier: Yes, that should work. > Now I need to ask, what happens when show_dialog_box throws an > exception? Presumably, I don't catch it in this code path, or there will > be a stack fault shortly. If the exception from show_dialog_box was thrown, and another CATCH handler fixed it for you, you don't need to worry about it - you can never know because you don't get access to that exception. It's as if it was never propagated. > One possibility is that the catcher of an exception knows little or > nothing about the innards of the thrower. It's the job of exception classes to bridge these - they have a class, and any number of attributes. Exception::IO::Open::PermissionDenied In fact I suspect that Exception::IO::Open enforces a certain type of fix, too: class Exception::IO::Open is Exception { has $.path; # what we tried to open has $.code; # the OS error code has $.mode; # the mode we attempted to open it with ... method resume (IO::Handle $thing) { $?SELF.SUPER::resume($thing); } } That way any bit of code that does: CATCH { when Exception::IO::Open { .. } } has documented, encapsulation safe tools to fix IO related errors, by redoing the call to open after remedying the situation. It doesn't need to know what code actually called open(). Nowadays to get "standard" behavior from a UI toolkit would you have to break abstraction and say My::Toolkit::open(...); to get semantics like a standard administrative access panel. With continuable exceptions you just use plain open, and the UI code can wrap your entire app with a rich standard library of exception handlers. > { > error_throwing_code(); > CATCH { > show_dialog_box(); > CATCH { > throw; # Pass the exception > show_dialog_box(); # Retry if I get resumed? > } > } > } > > That's going to get old, quickly. Just { error_throwing_code(); CATCH { show_dialog_box(); } } since the parent CATCH will resume from *inside* show_dialog_box. The abstraction of continuable exceptions should cascade. > But <c>resume</c> should be part of the Exception interface. Aye, see usefulness of this in above example. > >resuming. This is nice because especially if we're trying to e.g. > > > > my @handles = map { open $_ } @file_names; > > > >we can let the user skip unreadable files, by using return with no > >value instead of returning a handle. This is a generic pattern that > >enhances the user experience by not forcing the user to start over > >again. > > > >For more specific code, i doubt there will be several exceptions of > >the same kind in a call chain. > > > > > What's your example there? The "err undef" fashion, or the "pops up a > dialog box and then calls setuid()"? An exception ahndler that pops up a dialog box. In this case it would be: The file <x> could not be read: $! chmod it (chmod the file, and reopen it with same args) skip it (resume with no value) abort the program (rethrow instead of resume) Now, if the chmod operation had an exception like permission denied, obviously we are not the owner. To chown the file we need to setuid, and for that we need the user to authenticate. > I confess I find that (the dialog box) an amazing piece of work, but in > practical terms somebody someplace has to be doing a retry: I don't see > how it would work via resuming an exception. That's the point of continuable exceptions. When returning an exception from 'open' which is then thrown due to 'use fatal', the exception handler can then resume from the point where it was thrown, effectively replacing the exception object with a handle, that is then assigned to the variable: my $handle = open "file"; Under 'no fatal' $handle will have an exception object under 'use fatal' $handle will not be set at all... Unless the exception handler provides a different value to be put into $handle. > Unless Damian does it ;) I doubt even Damian likes to have all the lexical scopes his program made boo-boos in stay alive with no GC in case someone at some later point in the program decides that they can fix those errors. Also - after the code happenned, certain blocks of code will be repeated. This might be useful for obfuscation though ;-) > My suggestion here is that <c>with</c> load the dataspace of the > continuation atop the current environment. Yes, I see, but instead of doing it that way you can do it more safely with more characters by introspecting the exception object and using well documented attributes instead. -- () Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418 perl hacker & /\ kung foo master: /me groks YAML like the grasshopper: neeyah!!!!!!
pgpToU3cwMaqh.pgp
Description: PGP signature