Re: Exceptuations

2005-10-07 Thread Austin Hastings
Yuval Kogman wrote:

On Thu, Oct 06, 2005 at 14:27:30 -0600, Luke Palmer wrote:
  

On 10/6/05, Yuval Kogman [EMAIL PROTECTED] wrote:


when i can't open a file and $! tells me why i couldn't open, i
can resume with an alternative handle that is supposed to be the
same

when I can't reach a host I ask a user if they want to wait any
longer

when disk is full I ask the user if they want to write somewhere
else

when a file is unreadable i give the user the option to skip
  

I'm not bashing your idea, because I think it has uses.  But I'll
point out that all of these can be easily accompilshed by writing a
wrapper for open().  That would be the usual way to abstract this kind
of thing.



  

Writing a wrapper may be the implementation mechanics:

  sub safe_open()
  {
call;
CATCH { when E::AccessDenied { return show_user_setuid_dialog(); }}
  }

  open.wrap(safe_open);

But this is just one way to do it, and it fails to provide for helping
other people's code: Yuval's GUI environment would offer to fix the
problem for ALL file related calls (open, dup, popen, ad nauseum), and
would not have to worry about the order in which calls are wrapped. But
see below.

Stylistically I would tend to disagree, actually. I think it's cleaner to use 
exception handling for this.

Also, this implies that you know that the errors are generated by open. This 
is OK for open(), but if the errors are generated from a number of variants 
(MyApp::Timeout could come from anywhere in a moderately sized MyApp), then 
wrapping is not really an option.
  


I think that what your proposal *really* requires is uniformity. There
are other ways to get the same behavior, including an abstract factory
interface for exception construction (would provide virtual
constructor for exceptions, so permitting userspace to insert a 'retry'
behavior), but it has the same vulnerability: the p6core must cooperate
in uniformly using the same mechanism to report errors: throw, fail,
die, error, abend, whatever it's eventually called.

sub *::throw(...)
{
  return recover_from_error([EMAIL PROTECTED])
or P6CORE::throw([EMAIL PROTECTED]);
}

=Austin



Re: Exceptuations

2005-10-07 Thread Yuval Kogman
On Fri, Oct 07, 2005 at 02:31:12 -0400, Austin Hastings wrote:
 Yuval Kogman wrote:
 
 On Thu, Oct 06, 2005 at 14:27:30 -0600, Luke Palmer wrote:
   
 
 On 10/6/05, Yuval Kogman [EMAIL PROTECTED] wrote:
 
 
 when i can't open a file and $! tells me why i couldn't open, i
 can resume with an alternative handle that is supposed to be the
 same
 
 when I can't reach a host I ask a user if they want to wait any
 longer
 
 when disk is full I ask the user if they want to write somewhere
 else
 
 when a file is unreadable i give the user the option to skip
   
 
 I'm not bashing your idea, because I think it has uses.  But I'll
 point out that all of these can be easily accompilshed by writing a
 wrapper for open().  That would be the usual way to abstract this kind
 of thing.
 
 
 
   
 
 Writing a wrapper may be the implementation mechanics:
 
   sub safe_open()
   {
 call;
 CATCH { when E::AccessDenied { return show_user_setuid_dialog(); }}
   }
 
   open.wrap(safe_open);
 
 But this is just one way to do it, and it fails to provide for helping
 other people's code: Yuval's GUI environment would offer to fix the
 problem for ALL file related calls (open, dup, popen, ad nauseum), and
 would not have to worry about the order in which calls are wrapped. But
 see below.
 
 Stylistically I would tend to disagree, actually. I think it's cleaner to 
 use exception handling for this.
 
 Also, this implies that you know that the errors are generated by open. This 
 is OK for open(), but if the errors are generated from a number of variants 
 (MyApp::Timeout could come from anywhere in a moderately sized MyApp), then 
 wrapping is not really an option.
   
 
 
 I think that what your proposal *really* requires is uniformity. There
 are other ways to get the same behavior, including an abstract factory
 interface for exception construction (would provide virtual
 constructor for exceptions, so permitting userspace to insert a 'retry'
 behavior), but it has the same vulnerability: the p6core must cooperate
 in uniformly using the same mechanism to report errors: throw, fail,
 die, error, abend, whatever it's eventually called.

We have:

die: throw immediately

fail: return an unthrown exception, which will be thrown
depending on whether our caller, and their caller - every scope
into which this value propagates - is using fatal.

This is enough for normal exception handling.

As for recovery - the way it's done can be specialized on top of
continuations, but a continuation for the code that would run had
the exception not been raised is the bare metal support we need to
do this.

Where this gets taken further by (IMHO overly abstract) exception
handling libraries and standardization is a question that
application development kits (e.g. Catalyst, GTK, Cocoa) must
develop a policy for.

   return recover_from_error([EMAIL PROTECTED])

what does this do?

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me beats up some cheese: neeyah!



pgp3FUsw93RD9.pgp
Description: PGP signature


Re: Exceptuations

2005-10-07 Thread Yuval Kogman
On Fri, Oct 07, 2005 at 05:23:55 +0100, Piers Cawley wrote:
 Peter Haworth [EMAIL PROTECTED] writes:
 
  On Wed, 5 Oct 2005 19:24:47 +0200, Yuval Kogman wrote:
  On Wed, Oct 05, 2005 at 16:57:51 +0100, Peter Haworth wrote:
   On Mon, 26 Sep 2005 20:17:05 +0200, TSa wrote:
Piers Cawley wrote:
Exactly which exception is continued?
 The bottommost one. If you want to return to somewhere up its call
 chain, do:

   $!.caller(n).continue(42)
   
Whow, how does a higher level exception catcher *in general* know
what type it should return and how to construct it? The innocent
foo() caller shouldn't bother about a quux() somewhere down the line
of command. Much less of its innards.
   
   Well said.
  
  No! Not well said at all!
 
  Sorry, I misread that. I thought I was agreeng with how does a higher
  level exception catcher know what to change in order to make resuming the
  continuation useful?, especially in the light of Piers saying that the
  bottom-most exception should be the one resumed.
 
 I'm sorry, we appear to have lost some kind of context, the original example
 given only had one exception thrown, but it got propagated up through a long
 call chain. At no point did anything catch the original exception and
 rethrow. If they had, you're absolutely correct in asserting that by default
 things should resume from the point of the outermost rethrow. A brave 
 exception
 catcher (or more likely programmer with a debugger) might want to crack that
 exception open and examine its inner exceptions, but in general that's not
 going to be safe.

It doesn't really matter since 'fail'ed exceptions will simply be
converted to a return with the continued value when resumed, and
the question of outer/inner scopes is really irrelevant - it's like
tail calls.

As for die - since there is no implicit returning in die, it might
or might not make sense to try and resume. However, for most
situations it still looks to me like 'die foo' could be treated as
return in a way.

Essentially throwing an error means that the function/method who
threw it is giving up since it doesn't know how to resume.

If the exception handler can find an alternative for that function,
and replace the value, it's immediate caller should get the fixed
value, since they are the ones who need the value.

Functions which delegate exceptions are, again, just like tail
calls.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me wields bonsai kittens: neeyah



pgpjB4t4GbwlH.pgp
Description: PGP signature


Re: Exceptuations

2005-10-07 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


I'm not bashing your idea, because I think it has uses.  But I'll
point out that all of these can be easily accompilshed by writing a
wrapper for open().  That would be the usual way to abstract this kind
of thing.

 



My take on this: resumable exceptions break encapsulation no more (and 
no less) than using callbacks. The function that throws a resumable 
exception can only do this knowingly, and it could just as well offer a 
callback for that specific patchable error. So why take away a 
potentially highly useful tool?


BTW, two languages I know of have resumable exceptions: Common LISP and 
TOM. Neither supports continuations, instead, they separate raising 
exception (which runs a handler; this is implemented as a callback) from 
unwinding stack (which happens when the handler actually throws; it can 
choose to return instead, resuming execution if the raising function is 
okay with it). At least in Common LISP this is used a *lot* during 
interactive development, as it allows the developer to quickly patch 
things up without reruning the failed test. Assuming perl6 keeps the 
pugs-style interactive shell, I suspect resumable exceptions will be 
quickly added into the standard library if they don't pass into the 
standard. Yes, they're that useful.


   Miro




Re: Exceptuations (proposal for RESUME blocks)

2005-10-07 Thread TSa

HaloO

Yuval Kogman wrote:

We have:

die: throw immediately

fail: return an unthrown exception, which will be thrown
depending on whether our caller, and their caller - every scope
into which this value propagates - is using fatal.

This is enough for normal exception handling.


Is it only me seeing a self-contradiction in 'normal exception'?
But here are some ideas for renaming:

  resumeable exception - retro-fitted   pre-condition
  or: negotiated pre-condition

  or sumply resumption?

My mental picture is that of an outer scope in the call chain
attempting to meet the requirements communicated from an unknown
inner scope and then resuming where the failed pre-condition
was spotted. But I wouldn't require this to be implemented in
a very efficient way! When you need event handling, implement
it. E.g. the fail form needs to preserve the call chain
until the failure is handled. Handling might be as easy as
evaluation in void context or usage of // in a non-fatal scope.
Otherwise a CATCH block is needed. Or perhaps a RESUME block
and a correspondingly enhanced require form? That would integrate
the AUTODEF and friends with the error/exception/control/assertion
system. To illustrate the idea:

  if !$file.writeable { require $file.writeable; }

or perhaps even without the if. And then somewhere up the call chain

  RESUME
  {
 when .writeable { make $! writeable; resume }

 # more typeish syntax
 when File::writeable { make $! writeable; resume }
  }
  # with type outside
  RESUME File::writeable
  {
 make $! writeable; resume
  }

The resume could actually be the default way to exit a RESUME block.



As for recovery - the way it's done can be specialized on top of
continuations, but a continuation for the code that would run had
the exception not been raised is the bare metal support we need to
do this.


Yep, we need to agree on a form how to communicate unmet requirements
outwards. The only entity that comes to my mind that usually matches
requirements is the type system or meta information repository.



Where this gets taken further by (IMHO overly abstract) exception
handling libraries and standardization is a question that
application development kits (e.g. Catalyst, GTK, Cocoa) must
develop a policy for.


Well, yes! A non-trivial framework will install a bunch of types.
A subset of which beeing exception (sub)types. The challenge is then
shifted to inter-framework unification =8)
But one thing that should work is tunneling standard resumption requests
through such a framework.
--
$TSa.greeting := HaloO; # mind the echo!


Re: Exceptuations

2005-10-07 Thread Austin Hastings
Yuval Kogman wrote:

On Fri, Oct 07, 2005 at 02:31:12 -0400, Austin Hastings wrote:
  

Yuval Kogman wrote:



Stylistically I would tend to disagree, actually. I think it's cleaner to 
use exception handling for this.

Also, this implies that you know that the errors are generated by open. This 
is OK for open(), but if the errors are generated from a number of variants 
(MyApp::Timeout could come from anywhere in a moderately sized MyApp), then 
wrapping is not really an option.
 

  

I think that what your proposal *really* requires is uniformity. There are 
other ways to get the same behavior, including an abstract factory interface 
for exception construction (would provide virtual constructor for 
exceptions, so permitting userspace to insert a 'retry'
behavior), but it has the same vulnerability: the p6core must cooperate in 
uniformly using the same mechanism to report errors: throw, fail, die, error, 
abend, whatever it's eventually called.



We have:

   die: throw immediately

   fail: return an unthrown exception, which will be thrown
 depending on whether our caller, and their caller - every scope into which 
 this value propagates - is using fatal.

This is enough for normal exception handling.
  


Yet here we are discussiong abnormal exception handling.

As for recovery - the way it's done can be specialized on top of
continuations, but a continuation for the code that would run had
the exception not been raised is the bare metal support we need to
do this.
  


No, it isn't. It's *one way* to do this. Any mechanism which transfers
control to your error-recovery code in such a way that can cause an
uplevel return of a substituted value is the bare metal support we
need. You're conflating requirements and design.

I suggested an alternative *design* in my prior message, to no avail.
Try this instead:

You overload the global 'die' with a sub that tries to decode the error
based on its arguments. If it cannot comprehend the error, it invokes
P6CORE::die(). If it comprehends the error, it tries to resolve it
(querying the user, rebooting the machine to free up space in /tmp,
whatever) and if successful it returns the fixed value.

But wait! This requires that everyone do return die ... instead of
die..., and we can't have that. So you add a source filter, or macro, or
tweak the AST, or perform a hot poultry injection at the bytecode level,
or whatever is required to convert die into return die whereever it
occurs.

Et voila! No exceptions are caught, no continuations are released into
the wild. And yet it flies. Much like the hummingbird it looks a little
awkward, and I'm way not sure that munging bytecodes is necessarily a
better idea. But the point is that resuming from an exception (or
appearing to) is not bound to implemented with continuations.

=Austin

Et vidi quod aperuisset Autrijus unum de septem sigillis, et audivi
unum de quatuor animalibus, dicens tamquam vocem tonitrui : Veni, et
vide. Et vidi : et ecce camelus dromedarius, et qui scriptat super
illum, habebat archivum sextum, et data est ei corona, et exivit haccum
ut vinceret.
Apocalypsis 6:1 (Vulgata O'Reilly)


Re: Exceptuations

2005-10-07 Thread Yuval Kogman
On Fri, Oct 07, 2005 at 10:28:13 -0400, Austin Hastings wrote:

 But the point is that resuming from an exception (or
 appearing to) is not bound to implemented with continuations.

What's the point?

Continuations are good for exactly this purpose. Parrot already
supports them. I see absolutely no reason why we would want to
implement this any other way but using continuations.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: *shu*rik*en*sh*u*rik*en*s*hur*i*ke*n*: neeyah



pgpRP3mAuY8ah.pgp
Description: PGP signature


Re: Exceptuations

2005-10-06 Thread Yuval Kogman
On Wed, Oct 05, 2005 at 13:00:55 -0600, Luke Palmer wrote:

 I don't think it was a how is this possible, but more of a what
 business does it have?.  And as far as I gathered, they're saying
 pretty much what you've been saying, but in a different way.  It's
 about the continuation boundary; that is, if you're outside a module,
 you have no say in how the module does its business.  You can continue
 only at the module boundary, replacing a return value from its public
 interface.

As I see it this is the usefulness of exceptions being handled by
distant code.

The code in the module inverts it's interface by calling code it
doesn't know with a certain parameter, accepting a certain parameter
back.

That way encapsulation is not broken, but errors that happen deep
inside a call chain can be dealt with by code that can interact with
the user.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me climbs a brick wall with his fingers: neeyah!



pgpmp8WUodYYB.pgp
Description: PGP signature


Re: Exceptuations

2005-10-06 Thread Yuval Kogman
On Wed, Oct 05, 2005 at 13:41:37 -0700, Dave Whipp wrote:
 Reading this thread, I find myself wondering how a resumable exception 
 differs 
 from a dynamically scropted function. Imagine this code:

This is sort of like what I mean, except that there is no
encapsulation breakage, since the interface is inverted.

The advantage of this approach is that error handling code in a
submodule can benefit from generic, reusable exception handling code
that is provided by it's caller.

temp sub FileNotWriteable( Str $filename ) {

With an exception handler and continuable exceptions you don't have
to know what the error handler is, or make sure that the module
actually throws the error.

The exception handler instead deals with the type of the exception
in a generic manner (it doesn't care when the exception was actually
generated).

The module doesn't need to throw the error it just needs to fail (or
delegate a fail), until the failure crosses into a 'use fatal'
scope.

That way both the catching code and the throwing code are reusable
and orthogonal when they are unrelated, but the possibility of
coupling handling code with throwing code is still there.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me groks YAML like the grasshopper: neeyah!!



pgpzo38NCmZ47.pgp
Description: PGP signature


Re: Exceptuations

2005-10-06 Thread Peter Haworth
On Wed, 5 Oct 2005 19:24:47 +0200, Yuval Kogman wrote:
 On Wed, Oct 05, 2005 at 16:57:51 +0100, Peter Haworth wrote:
  On Mon, 26 Sep 2005 20:17:05 +0200, TSa wrote:
   Piers Cawley wrote:
   Exactly which exception is continued?
The bottommost one. If you want to return to somewhere up its call
chain, do:
   
  $!.caller(n).continue(42)
  
   Whow, how does a higher level exception catcher *in general* know
   what type it should return and how to construct it? The innocent
   foo() caller shouldn't bother about a quux() somewhere down the line
   of command. Much less of its innards.
  
  Well said.
 
 No! Not well said at all!

Sorry, I misread that. I thought I was agreeng with how does a higher
level exception catcher know what to change in order to make resuming the
continuation useful?, especially in the light of Piers saying that the
bottom-most exception should be the one resumed.

The highest level exception is the only one a caller has any right to deal
with, but even then it doesn't really know what will happen if it resumes
some random continuation attached to the exception.

   CATCH {
   when some_kind_of_error {
   $!.continue($appropriate_value_for_some_kind_of_error)
   }
   }

That just gives me the willies, I'm afraid.

-- 
Peter Haworth   [EMAIL PROTECTED]
Disconcerting Haworth Fortress Unicycling Melody Gundam
-- http://www.channel4.com/4later/bits/manga.html


Re: Exceptuations

2005-10-06 Thread Yuval Kogman
On Thu, Oct 06, 2005 at 18:11:38 +0100, Peter Haworth wrote:

 The highest level exception is the only one a caller has any right to deal
 with, but even then it doesn't really know what will happen if it resumes
 some random continuation attached to the exception.

But then we gain nothing

  CATCH {
  when some_kind_of_error {
  $!.continue($appropriate_value_for_some_kind_of_error)
  }
  }
 
 That just gives me the willies, I'm afraid.

Why?

when i can't open a file and $! tells me why i couldn't open, i
can resume with an alternative handle that is supposed to be the
same

when I can't reach a host I ask a user if they want to wait any
longer

when disk is full I ask the user if they want to write somewhere
else

when a file is unreadable i give the user the option to skip

These handlers are progressively more knowlegable of the code
they're dealing with, but they don't touch the actual guts - that's
the whole merit of continuable exception, because otherwise you
might aswell just start over.

These are 100% reusable in the first exception handler, and not
reusable but still applicable to an opaque call at the last handler.
It doesn't matter who opens the file file, the exception handler
will produce the same effect but in a different way.

CATCH {
when Error::IO::... {
open ...
}

when MyApp::Timeout {
ask_user_to_continue_or_abort();
}
...
}

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me dodges cabbages like macalypse log N: neeyah!



pgpQfW4BcQBM2.pgp
Description: PGP signature


Re: Exceptuations

2005-10-06 Thread Luke Palmer
On 10/6/05, Yuval Kogman [EMAIL PROTECTED] wrote:
 when i can't open a file and $! tells me why i couldn't open, i
 can resume with an alternative handle that is supposed to be the
 same

 when I can't reach a host I ask a user if they want to wait any
 longer

 when disk is full I ask the user if they want to write somewhere
 else

 when a file is unreadable i give the user the option to skip

I'm not bashing your idea, because I think it has uses.  But I'll
point out that all of these can be easily accompilshed by writing a
wrapper for open().  That would be the usual way to abstract this kind
of thing.

Luke


Re: Exceptuations

2005-10-06 Thread Yuval Kogman
On Thu, Oct 06, 2005 at 14:27:30 -0600, Luke Palmer wrote:
 On 10/6/05, Yuval Kogman [EMAIL PROTECTED] wrote:
  when i can't open a file and $! tells me why i couldn't open, i
  can resume with an alternative handle that is supposed to be the
  same
 
  when I can't reach a host I ask a user if they want to wait any
  longer
 
  when disk is full I ask the user if they want to write somewhere
  else
 
  when a file is unreadable i give the user the option to skip
 
 I'm not bashing your idea, because I think it has uses.  But I'll
 point out that all of these can be easily accompilshed by writing a
 wrapper for open().  That would be the usual way to abstract this kind
 of thing.

Stylistically I would tend to disagree, actually. I think it's
cleaner to use exception handling for this.

Also, this implies that you know that the errors are generated by
open. This is OK for open(), but if the errors are generated from a
number of variants (MyApp::Timeout could come from anywhere in a
moderately sized MyApp), then wrapping is not really an option.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me groks YAML like the grasshopper: neeyah!!



pgppFkb4LL0f1.pgp
Description: PGP signature


Re: Exceptuations

2005-10-06 Thread Piers Cawley
Peter Haworth [EMAIL PROTECTED] writes:

 On Wed, 5 Oct 2005 19:24:47 +0200, Yuval Kogman wrote:
 On Wed, Oct 05, 2005 at 16:57:51 +0100, Peter Haworth wrote:
  On Mon, 26 Sep 2005 20:17:05 +0200, TSa wrote:
   Piers Cawley wrote:
   Exactly which exception is continued?
The bottommost one. If you want to return to somewhere up its call
chain, do:
   
  $!.caller(n).continue(42)
  
   Whow, how does a higher level exception catcher *in general* know
   what type it should return and how to construct it? The innocent
   foo() caller shouldn't bother about a quux() somewhere down the line
   of command. Much less of its innards.
  
  Well said.
 
 No! Not well said at all!

 Sorry, I misread that. I thought I was agreeng with how does a higher
 level exception catcher know what to change in order to make resuming the
 continuation useful?, especially in the light of Piers saying that the
 bottom-most exception should be the one resumed.

I'm sorry, we appear to have lost some kind of context, the original example
given only had one exception thrown, but it got propagated up through a long
call chain. At no point did anything catch the original exception and
rethrow. If they had, you're absolutely correct in asserting that by default
things should resume from the point of the outermost rethrow. A brave exception
catcher (or more likely programmer with a debugger) might want to crack that
exception open and examine its inner exceptions, but in general that's not
going to be safe.

The scary syntax proposed above is, again, the sort of thing that might be
useful in a debugger I don't really care about the inner workings of these
helper functions, I just want 'open' to return this mocked handle. (actually
in that case, being able to do $!.caller(open).continue(MockIO.new), where
'caller open' looks up the call chain for the lowest call to open and returns
that continuation would be rather neat)

 The highest level exception is the only one a caller has any right to deal
 with, but even then it doesn't really know what will happen if it resumes
 some random continuation attached to the exception.

Oh stop with the 'rights'. And it's not dealing with a 'random' continuation,
if it's going to resume it should be damned careful about which exceptions it
resumes from; you don't just go around doing CATCH {...; $!.continue(...)}, you
do CATCH SomeSpecificKindOfResumableException { ...; $!.continue(...)}. And, in
general, you don't do that either, because in the average program you catch the
exception at a point where you can simply return a sensible default to your
caller. Resumable exceptions come into their own, however, when you're
debugging. I can envisage doing:

  perl6 -debug::on::error some_script

And have it run along happily until an exception gets propagated up to the top
level, at which point the debugger swings into action and uses the continuation
to tunnel back to the point at which the exception was thrown so the programmer
can inspect the program state, possibly fix things up, return something
sensible and carry on.

  CATCH {
  when some_kind_of_error {
  $!.continue($appropriate_value_for_some_kind_of_error)
  }
  }

 That just gives me the willies, I'm afraid.

It doesn't amuse me that much, unless whatever generates
$appropriate_value_for_some_kind_of_error is very, very smart indeed. But, as
I've said above, that's not really where resumable exceptions shine.

-- 
Piers Cawley [EMAIL PROTECTED]
http://www.bofh.org.uk/


Re: Exceptuations

2005-10-05 Thread Peter Haworth
On Mon, 26 Sep 2005 20:17:05 +0200, TSa wrote:
 Piers Cawley wrote:
 Exactly which exception is continued?
  The bottommost one. If you want to return to somewhere up its call
  chain, do:
 
$!.caller(n).continue(42)

 Whow, how does a higher level exception catcher *in general* know
 what type it should return and how to construct it? The innocent
 foo() caller shouldn't bother about a quux() somewhere down the line
 of command. Much less of its innards.

Well said.

 Think of receiving a 'shelf picker died of lung cancer' exception
 when you just ordered a book from your favorite book dealer.
 Irrespective of the seriousness to the shelf picker, but how would
 you expect a customer to handle such an exception?

This kind of exception should never get so far up the call chain,
except possibly as a nested cause of a more general exception. The
customer is in no position to get the book dealer to choose a
different stock picker - that's up to the order picking department of
the book shop. If it doesn't get handled there, then maybe the book
shop can try sourcing the book externally, and if that fails, they may
defer your order until later. The shop could ask the customer's
opinion as to the suitability of each of these options, but the
customer shouldn't have to know how the shop is implemented and make
such decision unprompted.

Even given a continuation to some low level routine, anything the
caller does is likely to be too far removed to make it sensible to
resume the continuation.

Eiffel deals with this by brutally its Design By Contract magic
bullet: Since all the code catching the exception knows about is its
own implementation, the only sane option it has is to try performing
the subtask in a different way. Here's how Eiffel's rescue/retry might
work in perl6, where rescue is spelled CATCH.

  class Picker{
# An individual order picker can pick a book, but may unfortunately
#   die of lung cancer, or just fail to find the book
method pick($book){
  fail Err::LungCancer if .is_smoker();
  ...
  fail Err::BookNotFound if ...;
}
  }

  class PickingDept{
# The picking department employs pickers to pick books
# If an employee dies of lung cancer while picking an order,
#   they are removed from the roster, and a different picker is chosen
# If the department doesn't have enough free pickers,
#   it just throws a too busy exception
# Due to the retry semantics, the department will keep choosing pickers
#   until one of them can pick the book, or they all die of lung cancer,
#   (or they're all busy doing something else)
method pick($book){
  my $picker=.find_free_picker();
  $picker.pick($book);
  ...

  CATCH{
when Err::NoPickersAvailable { fail Err::DeptTooBusy; }
when Err::LungCancer {
  .fire_picker($picker); # Harsh, but we won't find him again
  retry; # This re-runs the tried block (method) from the top
}
when Err::BookNotFound { fail Err::OutOfStock; } # Optimistic, maybe
default { fail; }
  }
}
  }

  class BookStore{
# The book store has multiple picking departments, so if one of them fails
# to find a book, the others can be tried. If that fails, they could order
# the book from the wholesaler and defer the order, but I'm too lazy
method order($book){
  for @.depts - $dept {
try{
  $dept.pick($book);
  return;
  
  CATCH{ 1; } # We'll just try the next one
}
  }
  fail Err::BookNotFound;
}

...
  }

  class Customer{
# The customer doesn't have any say in how bookshops are run, so all
# they can do if their order is refused, all they can do is try another
# shop, or give up and go home
method buy_book($book){
  $random_bookshop.order($book);

  CATCH{ fail Err::BookObviouslyDoesntExist; }
}
  }
  

-- 
Peter Haworth   [EMAIL PROTECTED]
Hestons' First Law: I qualify virtually everything I say.


Re: Exceptuations

2005-10-05 Thread Yuval Kogman
On Wed, Oct 05, 2005 at 16:57:51 +0100, Peter Haworth wrote:
 On Mon, 26 Sep 2005 20:17:05 +0200, TSa wrote:
  Piers Cawley wrote:
  Exactly which exception is continued?
   The bottommost one. If you want to return to somewhere up its call
   chain, do:
  
 $!.caller(n).continue(42)
 
  Whow, how does a higher level exception catcher *in general* know
  what type it should return and how to construct it? The innocent
  foo() caller shouldn't bother about a quux() somewhere down the line
  of command. Much less of its innards.
 
 Well said.


No! Not well said at all!

The exception handler knows *EVERYTHING* because it knows what
exception it caught:

CATCH {
when some_kind_of_error {
$!.continue($appropriate_value_for_some_kind_of_error)
}
}

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me climbs a brick wall with his fingers: neeyah!



pgpZ51c9ny7Ry.pgp
Description: PGP signature


Re: Exceptuations

2005-10-05 Thread Luke Palmer
On 10/5/05, Yuval Kogman [EMAIL PROTECTED] wrote:
 On Wed, Oct 05, 2005 at 16:57:51 +0100, Peter Haworth wrote:
  On Mon, 26 Sep 2005 20:17:05 +0200, TSa wrote:
   Whow, how does a higher level exception catcher *in general* know
   what type it should return and how to construct it? The innocent
   foo() caller shouldn't bother about a quux() somewhere down the line
   of command. Much less of its innards.
 
  Well said.


 No! Not well said at all!

 The exception handler knows *EVERYTHING* because it knows what
 exception it caught:

I don't think it was a how is this possible, but more of a what
business does it have?.  And as far as I gathered, they're saying
pretty much what you've been saying, but in a different way.  It's
about the continuation boundary; that is, if you're outside a module,
you have no say in how the module does its business.  You can continue
only at the module boundary, replacing a return value from its public
interface.

Of course, exactly how this public interface is declared is quite undefined.

Luke


Re: Exceptuations

2005-10-05 Thread Dave Whipp

Luke Palmer wrote:

Of course, exactly how this public interface is declared is quite undefined.


Reading this thread, I find myself wondering how a resumable exception 
differs from a dynamically scropted function. Imagine this code:


sub FileNotWriteable( Str $filename ) {
  die can't write file: $filename;
}

sub write_file (Str $filename)  {
  FileNotWriteable($filename) unless -w $filename;
  ...
}


sub my_program {

  temp sub FileNotWriteable( Str $filename ) {
return if chmod +w, $filename;
OUTER::FileNotWriteable( $filename );
  }

  ...
  write_file(foo.txt);
  ...
}


Ignoring syntactic sugar, what semantics does exception handling have 
that a dynamically scoped function does not?


In the case of non-resumable exceptions, we see things like deferred 
handling -- the exception is passed as a property of an undef value. I 
assume such an exception cannot be resumed, so it does appear to me that 
there are fundamental differences between resumable things, and 
non-resumable, deferrable, exceptions. What is the benefit of unifying 
them under a common syntax (CATCH blocks)?


Larry suggested that the exception mechanism might be a way of unifying 
errors and warnings; but perhaps the opposite is true. Perhaps what we 
see is a needed to generalize the distinction between warnigns and errors.



Dave.


Re: Exceptuations, fatality, resumption, locality, and the with keyword; was Re: use fatal err fail

2005-10-01 Thread Austin Hastings
.

  

that someone can catch these errors at the relevant place and quickly
tailor them. The right place, of course, is the sub or method that is
doing the work. I want to be able to CATCH local exceptions locally,
too! Not because I don't know what to do, but in a more Knuth/literate
sense, I don't want to write about what to do in-line with my beautiful
algorithm:

sub greet
{
  print Hello,  # or throw PrintException;
  print world\n # or throw PrintException;

  CATCH
  {
when PrintException {...}
  }
}

But I want to know which PART of my elaborate greeting failed. In the p5
version I could discriminate between first-part failure and second-part
failures. Why has p6 backslid into mealy-mouthed genericity?



It hasn't.. We still have 'or die' for raising exceptions, and you
can use, like you mentioned

  

One way, Yuval's suggestion, is to make err be a quicky catch mechanism:



It's not my suggestion, btw ;-)

  

Ah, sorry. I conflated the err thing with the Exceptuation thing. Mea
culpa.

sub greet
{
  print Hello,  err die Could not write first part;
  print world!\n err die Could not write second part;
}

But that's not abstracting anything. It just keeps the same, tedious,
check-every-result coding layout and gives it fractionally worse
Huffmanization.



Well, there is a conflict here:

you want to mark and not mark your errors at the same time.
  


Almost. I want exceptions, or exceptuations, to be sufficiently
transparent that I can use (below) some mechanism to infer details of
the problem without having to know too much of the internals below me
(but some, obviously); and I want all except(uat)ions to be potentially
resumable, except that some of them will override the resume
method/multi to avoid this.

But cresume/c should be part of the Exception interface.

  

What I want is to catch my errors elsewhere, and still
be able to localize their solution. Cleverly, there's already a way to
do this: labels. All I need is to know where I'm at, label-wise, and
I've got a dandy way to mark my code up.



This is feasable... I don't see why it shouldn't be implemented, but
frankly I don't see myself using it either.

This is because the types of exceptions I would want to resume are
ones that have a distinct cause that can be mined from the exception
object, and which my code can unambiguously fix without breaking the
encapsulation of the code that raised the exception.
  


Okay. So one way is to include a continuation in the exception. That
lets you resume, if the exception type is one you know. It lets me
inspect the code tree or call stack or whatever and process it in a
possibly invasive way, possibly resuming. I think we're in sync on this one.

These are all very specific and reusable, regardless of what we're
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()?

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.


[quote=http://java.sun.com/docs/books/tutorial/essential/exceptions/finally.html]
The final step in setting up an exception handler is to clean up before
allowing control to be passed to a different part of the program.



For cleanup we have real useful garbage collection, with a
declarative interface to decide on how an object needs to disappear.

Resource management is the task of the resource creator, not
exception handler, IMHO. It's just too hard to get it right.

So your point:

  

But resumptions are going to let us FIX the problem that occurred when
we tried to open the 256th filehandle. So all the directory parsing,
file exploring, and whatnot is going to be *preserved*.



is very valid

  

Thus we don't
actually want to automatically finalize all that stuff unless we know
for sure that we aren't going to resume: even *later* binding.



Continuations give this behavior consistently.

They just need to be garbage collected themselves, in a way.

What I would like to disallow is the ability to take $! and just
.resume it out of the blue in code that isn't an exception handler.
That just does't make sense:

   try { ... }
   some_other_stuff;
   $!.resume if $!;
  


Unless Damian does it ;)

Yet another use for a Pascal's cwith/c keyword:



I actually quite liked that RFC =)

The problem is that records in a static language are static, and
hashes are dynamic.

There is no way to tell the user at compile time

Re: Exceptuations, fatality, resumption, locality, and the with keyword; was Re: use fatal err fail

2005-10-01 Thread Austin Hastings
TSa wrote:


 The view I believe Yuval is harboring is the one examplified
 in movies like The Matrix or The 13th Floor and that underlies
 the holodeck of the Enterprise: you can leave the intrinsic
 causality of the running program and inspect it. Usually that
 is called debugging. But this implies the programmer catches
 a breakpoint exception or some such ;)

 Exception handling is the programmatic automatisation of this
 process. As such it works the better the closer it is in time
 and context to the cause and the more information is preserved.
 But we all know that a usefull program is lossy in that respect.
 It re-uses finite resources during its execution. In an extreme
 setting one could run a program *backwards* if all relevant
 events were recorded!


The current state of the art dictates that exceptions are to be avoided
when it is possible to handle the error in-line. That exceptions should
only be used for exceptional cases, and anything you encounter in the
manual pages is not exceptional.

I don't agree with this, because it is IMO effectively saying We had
this powerful notion, but it turned out to be difficult to integrate
post-hoc into our stack-based languages, so we're going to avoid it.
Rather than admitting defeat, though, we're going to categorize it as
some kind of marginal entity.

I don't see exceptions as necessarily being outside the intrinsic
causality of the running program. They are non-traditional forms of flow
control: event-based programming, if you will, in an otherwise
sequential program.

We do much the same thing when we talk about coroutines: violate the
traditional stack model. We do the same thing again when we talk about
aspects: de-localize processing of certain (ahem) aspects of the problem
domain. The telling part of aspects, though, was the the first popular
implementation (AspectJ) required a preprocessor and a special markup
language to implement. Why? Because nobody uses extensibility and Java
in the same sentence. I guess aspects are traditional in that regard,
though: remember CFront. Perl, OTGH, doesn't have the poor body-image or
whatever it is that keeps people afraid to change the syntax.

 It can't be a method because it never returns to it's caller - it's


 It beeing the CATCH block? 


Ahh, no. It in this case is the .resume call. My question was is
cresume/c a multi, an object method, or what?

 This is because the types of exceptions I would want to resume are
 ones that have a distinct cause that can be mined from the exception
 object, and which my code can unambiguously fix without breaking the
 encapsulation of the code that raised the exception.


 Agreed. I tried to express the same above with my words.
 The only thing that is a bit underspecced right now is
 what exactly is lost in the process and what is not.
 My guiding theme again is the type system where you leave
 information about the things you need to be preserved to
 handle unusual cicumstances gracefully---note: *not*
 successfully, which would contradict the concept of exceptions!


This is the classical view of exceptions, and so it is subject to the
classical constraints: you can't break encapsulation, so you can't
really know what's going when the exception occurs.

The reason I like the with approach is that it lets us delocalize the
processing, but does _not_ keep the exceptions are violent,
incomprehensible events which wrench us from our placid idyll mentality.

In that regard, exceptuations are resumable gotos.

=Austin



Re: Exceptuations, fatality, resumption, locality, and the with keyword; was Re: use fatal err fail

2005-10-01 Thread Yuval Kogman
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 

Re: Exceptuations

2005-09-30 Thread Piers Cawley
TSa [EMAIL PROTECTED] writes:
 BTW, I would call *intentional* exceptions terrorism.

So that would be all exceptions then. They all get implemented somewhere, even
the ones that get thrown by builtins.

  CATCH Exception { say Why do you hate freedom? }

-- 
Piers Cawley [EMAIL PROTECTED]
http://www.bofh.org.uk/


Re: Exceptuations, fatality, resumption, locality, and the with keyword; was Re: use fatal err fail

2005-09-30 Thread TSa

HaloO,

Yuval Kogman wrote:

The try/catch mechanism is not like the haskell way, since it is
purposefully ad-hoc. It serves to fix a case by case basis of out
of bounds values. Haskell forbids out of bound values, but in most
programming languages we have them to make things simpler for the
maintenance programmer.


My view here is that the parameters in the code pick a point in
the range from free on the one end and bound at the other end.
The unifying concept is constraints. So I see the following boundary
equalities:

  unconstraint = free  # 0.0
  contstraint  # 0.0^..^1.0
  fully constraint

as the black and white ends with shades of gray in the middle.
And it is the type system that guaranties the availability
of the required information e.g. in $!. In that sense a sub
with a CATCH block is a different type than one without. This
difference is taking into account when dispatching exceptions.



Reentrancy is an implementation detail best left unmentioned.


Uh ohh, in an imperative language with shared state outside
the unshared state of multiple invocations of one sub the reentrance
proplem is just there. Interestingly it is easily unifyable with
shared data.



Assume that every bit of code you can run in perl 6 is first class
code - it gets safety, calls, control flow, exceptions, and so
forth.


Just to synchronize our understanding, I see the following
equivalences from the data and code domains

datacode

class = sub
 instance = invocation

To illustrate my view consider

class foo
{
   has ...
   method ...
}

and match with

sub foo
{
   has ... # my named parameters defined in body proposal

   BEGIN ...
   CATCH ...

   label:
}

What I want to say is that calling a sub means creating an
instance of the class that describes---or *constrains*---
the potential invocations. If such an invocation is left
lying in memory unfinished we have a continuation. How concurrent
these continuations are stepped in real time with respect to their
respective inner causal logic is irrelevant to the concept.
But *causality* is important!

The view I believe Yuval is harboring is the one examplified
in movies like The Matrix or The 13th Floor and that underlies
the holodeck of the Enterprise: you can leave the intrinsic
causality of the running program and inspect it. Usually that
is called debugging. But this implies the programmer catches
a breakpoint exception or some such ;)

Exception handling is the programmatic automatisation of this
process. As such it works the better the closer it is in time
and context to the cause and the more information is preserved.
But we all know that a usefull program is lossy in that respect.
It re-uses finite resources during its execution. In an extreme
setting one could run a program *backwards* if all relevant
events were recorded!



Yes, even signals and exceptions.

The runtime is responsible for making these as fast as possible
without being unsafe.


Hmm, I would see the type system in that role. It has all the
information of the interested parties in a longjump. If it knows
there are no potential handlers




It can't be a method because it never returns to it's caller - it's


It beeing the CATCH block? Then I think it *is* in a certain
way a method with $! as it's invocant. HiHi and here a locality
metric for dispatch applies. BTW, how is the signature of a CATCH
block given? Simply

   CATCH SomeException {...}

or is inspection with cascaded when mandatory?



a continuation because it picks up where the exception was thrown,


I would say it is given information about. In a way an exception
handler is dispatched on the type of exception.


and returns not to the code which continued it, but to the code that
would have been returned to if there was no exception.


This is the thing that I see is hardly possible from a far away scope.
But fair enough for closely related code.



It is, IMHO a multi though. There is no reason that every
continuation cannot be a multi, because a continuation is just a
sub.

I don't know if there are method continuations - i guess there could
be, but there's no need to permutate all the options when the
options can compose just as well.


My view is that a (free) method type becomes a continuation
as follows:

  1) the invocant type is determined
  2) the dispatcher selects a matching target
  3) this method maker object (like a class for constructing data objects)
 is asked to create a not yet called invocation and bind it to the
 invocant at hand
  4) at that moment we have a not yet invoked sub instance, so
 plain subs just start here
  5) The signature is checked and bound in the environment of the calling
 scope, the callers return continuation is one of the args
  6) then this invocation is activated
  7a) a return uses the return continuation in such a way that
  the invocation is abandoned after the jump
   b) a yield keeps the continuation just like a constructed object
  and 

Re: Exceptuations

2005-09-30 Thread TSa

HaloO Piers,

you wrote:

TSa [EMAIL PROTECTED] writes:


BTW, I would call *intentional* exceptions terrorism.



So that would be all exceptions then. They all get implemented somewhere, even
the ones that get thrown by builtins.


I knew that the statement would emotionalize. Sorry to all who don't
like it an this list. But somehow I found it describes the impression
on the handling side somewhat. And I thought it illustrates that exceptions
shouldn't be considered just another tool.




  CATCH Exception { say Why do you hate freedom? }



I don't. But the freedom of the individual ends where the
community begins.
--
$TSa.greeting := HaloO; # mind the echo!


Re: Exceptuations

2005-09-30 Thread Yuval Kogman
On Fri, Sep 30, 2005 at 18:02:46 +0200, TSa wrote:
 I knew that the statement would emotionalize. Sorry to all who don't
 like it an this list. But somehow I found it describes the impression
 on the handling side somewhat. And I thought it illustrates that exceptions
 shouldn't be considered just another tool.

I think you're taking it too seriously. I'm 99% sure Piers was
joking.

Regardless, exceptions *are* just another tool. They let you write
safe code in fewer words and with less distraction.

For example, Either you linearly serialize the entire tree of
possible events:

if (my $handle = open file) {
# the handle is open
if (my $other_file = open other :w) {
for =$handle - $line {
unless ($other_file.print($line)) {
$*ERR.print(other could not be written 
to: $!); # disk might be full
if (close $other_file) {
if (close $handle) {
exit 1;
} else { ...; exit 1 }
} else { ...; exit 1 }
}
exit 0;
}
} else {
$*ERR.print(could not open other for writing: $!);
if (close $handle) {
exit 0;
} else {
$*ERR.print(could not close file: $!); # not 
logical,
# since we don't write to file, but this is 
safer
exit 1;
}
}
} else {
print $*ERR, could not open file: $!;
exit 1;
}

or you could throw exceptions:

use fatal;

my $handle = open file;
my $other_file = open other :w;

for =$handle - $line {
$other_file.print($line);
}

If you are going to avoid exceptions because they are too much
something for your taste, then I think you are misusing a language
that has support for exceptions.

I really don't understand why this has to do with freedom, or it's
restriction. It's your personal (and IMHO bad) taste not to use
exceptions for improving your code, but it's still your choice.

All I was saying is that you could leverage exceptions by letting
the UI code make the handling of exceptions a two way route, instead
of one way.

   CATCH Exception { say Why do you hate freedom? }
 
 I don't. But the freedom of the individual ends where the
 community begins.

I think this is a big exaggeration. The community will not be harmed
if the individual uses exceptions.

On the contrary, i would be much happier to use code that does
through exceptions.

For example, a very useful perl 5 module, UNIVERSAL::require, lets
me write:

$class-require or die $UNIVERSAL::require::ERROR;

instead of

eval require $class; die $@ if $@;

but in both cases I have to check for errors, unlike

require Class;

I still prefer $class-require, though, because it feels more
readable to me. I don't say to myself wtf? why is this code doing
an eval while reading the code.

In perl 6, we would ideally have:

use fatal;
$class.require; # lives if class exists, dies if class doesn't exist
$class.method; # always lives (if method really exists)

or
use fatal;
try { $class.require } # always lives
$class.method; # might die, but at least it's obvious

or

no fatal;
$class.require; # always lives\
$class.method; # might die

In fact UNIVERSAL::require's author agrees with me:
http://use.perl.org/~schwern/journal/26939

Now, if this were 

#!/usr/bin/perl

use fatal;
use Pluginish::App;

sub infix:s~ ($l, $r) { $l $r }; # spacey concatenator

{
Pluginish::App-load_plugins;
CATCH {
when Module::load_error {
if (prompt(The module $!.module_name could not 
be loaded because
   s~  an error occurred ($!). Try to 
continue anyway?) {
$!.resume(undef);
} else {
die $!;
}
}
}

Pluginish::App-run;

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /methinks long and hard, and runs away: neeyah!!!



pgpKTxHNv1uR1.pgp
Description: PGP signature


Re: Exceptuations

2005-09-29 Thread TSa

HaloO,

Yuval Kogman wrote:

On Wed, Sep 28, 2005 at 09:49:11 -0700, Larry Wall wrote:

But thinking about optional continuations, another thing occured
to me.  It's always bugged me that warnings were something different
from exceptions, and now I think we can unify them, if we say that


Yes, I'm also all for unifying the concepts. But please
don't let us call it exception. Exception should be a
termination oriented (sub)concept. Some kind of scoped giving
up. E.g. a traffic accident is the exceptual case that
stops the regular traffic in a certain area. But for
medics, firemen and police they are the usual case up to
a limit where it also becomes exceptional to them.

Take the example of firemen. They are some kind of installed
exception handlers. And they can handle flooded basements
but New Orleans and Bavaria have thrown a too big exception.
Well, or take the engineers of the Titanic, they trusted their installed
exception handlers to cope with a breached hull so much that they
didn't install enough rescue boats.

BTW, I would call *intentional* exceptions terrorism.




a warning is simply an exception with two properties.
or have a WARN block of its own, I don't know.



Or maybe *EXCEPTION_HANDLER is a multi-method-continuation.
...
An MMD exception handler that is extended in the dynamic scope is
cool because it's not limitied to just control exceptions, warnings,
and fatal errors.

Some fun definitions:


In lack of a better word I use Event and we get
Event::Exception, Event::Control, Event::Warn and
possibly Event::Hint, Event::Log and Event::Fun :)

The only drawback of choosing 'Event' might be that it
smells too GUIish for some? Or is that a feature? That is
we get Event::GUI::press, Event::GUI::scroll, Event::GUI::expose,
etc.
--
$TSa.greeting := HaloO; # mind the echo!


Re: Exceptuations

2005-09-29 Thread Yuval Kogman
Hi!

On Thu, Sep 29, 2005 at 10:49:40 +0200, TSa wrote:
 BTW, I would call *intentional* exceptions terrorism.

Then I would call terrorism non linear control flow ;-)

In that case Afghanistan might be harboring computer scientists that
really like CPS, and bush is Java ;-)

 In lack of a better word I use Event and we get
 Event::Exception, Event::Control, Event::Warn and
 possibly Event::Hint, Event::Log and Event::Fun :)

An event is something external that happens... It does not affect
the control flow of an application.

Exceptions work well to describe this:

The normal flow is up and down the call graph, laying bread crumbs
in the form of a stack, and going back from where you came.

Exceptions let you jump instantly to another place in the call
graph. All I'm saying is that to complement the normal exceptions
jump back out, you can jump out, and jump back in.

An event is a general thing that can be implemented with exception
like semantics, but implies nothing on the control flow of the
program.

An error is an exception that happenned because something went badly
wrong.


Now it's my turn at illustrative metaphors ;-)

The call graph is a big maze you go through.

When you find an *error*, in the form of a minotaur, you use the
exception handling mechanism to run away.

You jump instantly to a safe place in the labyrinth.

Although this is not consistent with the mythology, presume that the
reason you entered the maze was that you were trying to get results.

Most exception handlers are safe places when you can gather your
self, realize that 'oh crap, i just met a minotaur', and tell
whoever you sent you in there that there's no way you're going back
in.

All I'm trying to say is that when there is an exception - a leap
out from a dangerous place to a safe one, due to an error, the code
may choose to deal with the error by giving you a big stick. Then
you can go back and beat the minotaur into submission, and resume
with trying to get results.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me whallops greyface with a fnord: neeyah!!!



pgp9mjhsoAPUd.pgp
Description: PGP signature


Re: Exceptuations

2005-09-29 Thread Yuval Kogman
I'd like to ammend, and perhaps formalize with some definitions from
my dictionary, which ships with OSX:

error - a mistake... the state or condition of being wrong in
conduct or judgement... technical - a measure of the estimated
difference between the observed or calculated value of a
quantity and it's true value.

As i see it:

when something you wanted to happen turned out different than
you programmed it to:

my $handle = open file;
# we assume $handle exists
print =$handle; # but what if there was an error?



exception - a person or thing that is excluded from a general
statement or does not follow a rule

To lessen the mental load on a programmer, instead of having the
programmer write a tree of all the conditions that could happen, the
programmer can write only the condition in which the program is
actually useful.

Any *error* (synch problems between the code and reality) causes an
*exception* in this linearization. The control flow is an exception
to the norm, because there was an exception in the reality the
program was tailored to deal with.

The reason we handle exceptions is that sometimes we want the tree
approach, because we have well defined behavior for certain paths.
Exceptions let us separate code from normal code and code which is
*exceptional*, and the reason it is exceptional is usually an error.



event - a thing that happens, especially one of importance

Every error is an event. Exceptions are one way to deal with events
we were not prepared for. But events can also be waited for (select
waits for events on many file handles at a time).

Every *error* is an *event*, but an *exception* is how you deal with
events. The events that cause exceptions by default in perl will be:

errors, when 'use fatal' is in effect

warnings, but to another handler

next, redo, last, return - all control flow events that are
exceptions to the single point of entry, single point of exit
school of thought.

I intentionally did not use the computer related definitions from
e.g. wikipedia, because they are more subject to cultural inertia,
and we are trying to discover the roots of these borrowed terms.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me groks YAML like the grasshopper: neeyah!!



pgpr89lYnXBsX.pgp
Description: PGP signature


Re: Exceptuations

2005-09-29 Thread Ruud H.G. van Tol
TSa schreef:

 Yes, I'm also all for unifying the concepts. But please
 don't let us call it exception. Exception should be a
 termination oriented (sub)concept. Some kind of scoped giving
 up. [...]
 In lack of a better word I use Event and we get
 Event::Exception, Event::Control, Event::Warn and
 possibly Event::Hint, Event::Log and Event::Fun :)

 The only drawback of choosing 'Event' might be that it
 smells too GUIish for some? Or is that a feature? That is
 we get Event::GUI::press, Event::GUI::scroll, Event::GUI::expose,
 etc.


FSM etc.
http://en.wikipedia.org/wiki/Event_driven_finite_state_machine

Running Perl code can be seen as an ATN (an FSM on steroids, says
http://smc.sourceforge.net/SmcFaq.htm).

An exception-handler can be allowed to pop more states than it is good
for.

-- 
Grtz, Ruud



Exceptuations, fatality, resumption, locality, and the with keyword; was Re: use fatal err fail

2005-09-29 Thread Austin Hastings
TSa wrote:

 HaloO,

 Yuval Kogman wrote:

 On Wed, Sep 28, 2005 at 11:46:37 -0500, Adam D. Lopresto wrote:

 The recent thread on Expectuations brought back to mind something
 I've been
 thinking for a while.  In short, I propose that use fatal be on by
 default, and
 that err be turned into syntactic sugar for a very small try/CATCH
 block.



You already know that err is the low-precedence version of //, right?
What replaces that? I like default or defaults myself, but I'm never
really sure what the precedence actually IS. After all, and/or were
lower than assignment, so you could code:

$a = foo or die;

and get ($a or die). How does this work for the err/defaults
keyword? Does the low-precedence version move up, or is there an idiom I
don't understand?

On the primary hand, I don't like the idea of using err as a try/catch
because that's putting exception handling in line with the primary code.
See FMTYEWT below.


 I like it a lot. It gives the advantages of both the flexible, more
 robust try/catch, and the (locally) concise, clear error return.


 I don't like it at all. I fear, that we mix two orthogonal concepts
 just because it is convenient.

 To me the statement

   return 42;  # 1

 has to orthogonal meanings:

   1) the current scope has reached its (happy) end
   2) a specific result was determined

 We can vary on both of these dimensions *independently*!
 Which gives the remaining three cases:

   return undef; #  0   unspecific result
   fail   undef; # -1   no return with unspecific reason
   fail   42;# -2   no return but  determined reason

 In other words an exception means

   return !caller;

 or in yet another way to describe my attitude: the least
 thing that *defines* an exception is that the dynamic
 scope in question has reached the conclusion that it
 is *not* going to give control back to its creator!


But it *does* give control, albeit briefly, back to its caller.

A million years ago, $Larry pointed out that when we were able to use
'is just a' classifications on P6 concepts, it indicated that we were
making good forward progress. In that vein, let me propose that:

* Exception handling, and the whole try/catch thing, IS JUST An awkward
implementation of (late! binding) run-time return-type MMD.

Specifically, if I promise you:

  sub foo() will return Dog;

and later on I actually wind up giving you:

  sub foo() will return Exception::Math::DivisionByZero;

the try/catch paradigm essentially says:

I wanted to call csub Dog foo()/c but there may be times when I
discover, after making the call, that I really needed to call an anonymous
csub { $inner::= sub Exception foo(); $e = $inner(); given $e {...} }/c.

We're conditionally editing the return stack. This fits right in with
the earlier thread about conditionally removing code from the inside of
loops, IMO. Once you open this can, you might as well eat more than one
worm. Another conceptually similar notion is that of AUTOLOAD. As a perl
coder, I don't EVER want to write

  say Hello, world
or die Write to stdout failed.;

-- it's correct. It's safe coding. And it's stupid for a whole bunch
of reasons, mostly involving the word yucky. But I acknowledge that
through the miracle of broken pipes, it can legitimately happen that
stdout will fail while stderr is a viable diagnostic mechanism.

Instead, I want PERL to fill that in for me: I believe that the default
error mechanism should debug my program, the shell script that calls my
program, and the actions (including blood alcohol content) of the user
of my program over the last 24 hours: lets leave cuse autodebug;/c
turned on by default.

The 'Exceptuation' proposal seems to me to include two things:

1. A 'RESUME' feature.
2. An implicit acknowledgement that the default implementations are
parallel:

{...
  CATCH  - $e {throw $e;} # Going up?
  RESUME - $r {resume $r;} # Going down?
}

The rest is optimization. If caller() includes an array of
continuations, then cthrow/c looks like a loop up the array:

  sub throw(Exception $e)
  {
reverse caller() == { .continuation($! = $e) if does(CATCH); }
  }

But the default behavior (modulo threads) is going to unlink all the
stack frame pages when the continuation is invoked. So there has to be
yet another copy of the links to the stack, because the exception
handling will want to call functions and build who-knows-what elaborate
skycastles. And it must be reentrant because of the possibility of
exceptions during the exception handling. Which means that the call
stack needs to be stored in the Exception. [The list of things in the
exception gets pretty long. I'm sure it's all a ref to the last page of
the call stack, so it doesn't gobble up much space, but there's a lot of
and you'll wants coming up.]

So cresume/c is a multi, no? (Or it could just be a method:
$!.resume, but that doesn't read as well in a block that *really* should
be as readable as possible.) Also, any layer of exception handling may
do some 

Re: Exceptuations, fatality, resumption, locality, and the with keyword; was Re: use fatal err fail

2005-09-29 Thread Yuval Kogman
On Thu, Sep 29, 2005 at 13:52:54 -0400, Austin Hastings wrote:

 You already know that err is the low-precedence version of //, right?
 What replaces that? I like default or defaults myself,

Yes, he proposed 'dor'.

As I see it err is like this:

sub infix:err ($lhs is delayed, $rhs is delayed) { # we really need 
thunk parameters
return $lhs dor $rhs;
CATCH { return $rhs }
}

So really 'err' is just 'dor' with an added error silencer.

 On the primary hand, I don't like the idea of using err as a try/catch
 because that's putting exception handling in line with the primary code.
 See FMTYEWT below.

Isn't

no fatal;

my $fh = open $file or die;
...
my $fh = open $file or next;

also putting exception handling in line with the primary code?

Isn't that useful?

Exception handling should be put in wherever there is well defined
behavior on how error conditions should be dealt with.

It's Perl's job to make this as easy as possible for the programmer.

If we have a module called File::Slurp::Some, which doesn't really
care if some of the files don't exist, it's code would, IMHO be
much more readable with

open $file err next;

than a catch block.

The reason for this is that a catch block is always detached from
the code.

However, if the error is part of the normal flow (it is no longer
exceptional for the file to not exist), what benefit does the added
detachment give?

 A million years ago, $Larry pointed out that when we were able to use
 'is just a' classifications on P6 concepts, it indicated that we were
 making good forward progress. In that vein, let me propose that:
 
 * Exception handling, and the whole try/catch thing, IS JUST An awkward
 implementation of (late! binding) run-time return-type MMD.

Exception handling is just continuation passing style with sugar.

Have a look at haskell's either monad. It has two familiar keywords
- return and fail.

Every statement in a monadic action in haskell is sequenced by using
the monadic bind operator.

The implementation of =, the monadic bind operator, on the Either
type is one that first check to see if the left statement has
failed. If it does, it returns it. If it doesn't it returns the
evaluation of the right hand statement.

Essentially this is the same thing, just formalized into a type

 Specifically, if I promise you:
 
   sub foo() will return Dog;
 
 and later on I actually wind up giving you:
 
   sub foo() will return Exception::Math::DivisionByZero;

In haskell:

foo :: Either Dog Exception::Math::DivisionByZero

e.g., it can return either the expected type, or the parameter.

Haskell is elegant in that it compromises nothing for soundness, to
respect referential integrity and purity, but it still makes thing
convenient for the programmer using things such as monads


 the try/catch paradigm essentially says:
 
 I wanted to call csub Dog foo()/c but there may be times when I
 discover, after making the call, that I really needed to call an anonymous
 csub { $inner::= sub Exception foo(); $e = $inner(); given $e {...} }/c.

Yes and no.

The try/catch mechanism is not like the haskell way, since it is
purposefully ad-hoc. It serves to fix a case by case basis of out
of bounds values. Haskell forbids out of bound values, but in most
programming languages we have them to make things simpler for the
maintenance programmer.

 We're conditionally editing the return stack. This fits right in with
 the earlier thread about conditionally removing code from the inside of
 loops, IMO. Once you open this can, you might as well eat more than one
 worm. Another conceptually similar notion is that of AUTOLOAD. As a perl
 coder, I don't EVER want to write
 
   say Hello, world
 or die Write to stdout failed.;
 
 -- it's correct. It's safe coding.  And it's stupid for a
 whole bunch of reasons, mostly involving the word yucky.

It's incorrect because it's distracting and tedious.

http://c2.com/cgi/wiki?IntentionNotAlgorithm

Code which does it is, IMHO bad code because obviously the author
does not know where to draw the line and say this is good enough,
anything more would only make it worse.

 But I acknowledge that through the miracle of broken pipes, it can
 legitimately happen that stdout will fail while stderr is a viable
 diagnostic mechanism.

the default $SIG{PIPE} handler is a wonderful example of how nice
exception handling is for naive code.

$SIG{PIPE}'s only problem is that it's completely non standard.

 But the default behavior (modulo threads) is going to unlink all the
 stack frame pages when the continuation is invoked.

Forget the stack... Perl is CPS under the hood, even if it's
optimized not to be that way.

 So there has to be yet another copy of the links to the stack,
 because the exception handling will want to call functions and
 build who-knows-what elaborate skycastles. And it must be
 reentrant because of 

Re: Exceptuations

2005-09-28 Thread Larry Wall
I'd like to add a little more.  The context of the original throw
probably knows best whether it's even possible or sensical to
continue, so it should be optional whether the exception contains a
resume continuation.  The presence of the continuation signals that
the inner code would *like* to continue but can't figure out how
without more dynamic context, where that could even include human
interaction on some level.  The absence of a resume continuation
means someone thinks this dynamic branch needs a wooden stake through
its heart.

But thinking about optional continuations, another thing occured
to me.  It's always bugged me that warnings were something different
from exceptions, and now I think we can unify them, if we say that
a warning is simply an exception with two properties.  The first is
that it's in a category that, by default, the outermost runtime will
just report on and resume.  And the second is, of course, that the
resume continuation is required.  So turning any warning into a
fatal error consists of stripping the resume continuation.  (Which
might mean that the presence of the continuation is what differentiates
warnings from fatal errors, but I doubt it.  There needs to be a
class of exceptions that have a resume continuation that is not resumed
by default.  A die should throw that kind of exception, and have
a reasonably expectation of not being resumed in the normal course of
things.  Nevertheless, a die is well formed enough that we know where
it should resume if it forced into a warning instead.)

This gives us the ability to capture any warning in the dynamic
scope and do something about it.  (Whether it should by default
pop up in a CATCH block or a CONTROL block, or have a WARN block
of its own, I don't know.)  But this gives us dynamic control over
warnings to complement (not replace) the lexical control provided by
use warnings.

Larry


Re: Exceptuations

2005-09-28 Thread Yuval Kogman
On Wed, Sep 28, 2005 at 09:49:11 -0700, Larry Wall wrote:
 I'd like to add a little more.  The context of the original throw
 probably knows best whether it's even possible or sensical to
 continue, so it should be optional whether the exception contains a
 resume continuation.  The presence of the continuation signals that
 the inner code would *like* to continue but can't figure out how
 without more dynamic context, where that could even include human
 interaction on some level.  The absence of a resume continuation
 means someone thinks this dynamic branch needs a wooden stake through
 its heart.
 
 But thinking about optional continuations, another thing occured
 to me.  It's always bugged me that warnings were something different
 from exceptions, and now I think we can unify them, if we say that
 a warning is simply an exception with two properties.  The first is
 that it's in a category that, by default, the outermost runtime will
 just report on and resume.  And the second is, of course, that the
 resume continuation is required.  So turning any warning into a
 fatal error consists of stripping the resume continuation.  (Which
 might mean that the presence of the continuation is what differentiates
 warnings from fatal errors, but I doubt it.  There needs to be a
 class of exceptions that have a resume continuation that is not resumed
 by default.  A die should throw that kind of exception, and have
 a reasonably expectation of not being resumed in the normal course of
 things.

So CATCH does set the *EXCEPTION_HANDLER continuation to be something
like:

given $! {
when Exception::ResumesByDefault {
old_exception_handler($!);
}

... # the body of the CATCH
}

and 

 or have a WARN block of its own, I don't know.

Or maybe *EXCEPTION_HANDLER is a multi-method-continuation.

CATCH could simply be a macro that compiles to

ENTER {
temp *EXCEPTION_HANDLER := *OUTER::EXCEPTION_HANDLER;
EXCEPTION_HANDLER.add_variant(cont (Exception::Fatal $!) {

};
}

BTW, how do we declare continuations explicitly? Or is it just a sub
that is directly .goto'd ?

An MMD exception handler that is extended in the dynamic scope is
cool because it's not limitied to just control exceptions, warnings,
and fatal errors.

Some fun definitions:

every loop construct creates some lexical bindings in the body:

next - throws an Exception::Control::Next
redo - throws an Exception::Control::Redo
...

Entering the loop adds temporary variants to
*EXCEPTION_HANDLER:

multi cont (Exception::Control::Redo) {
body.goto(*$current_binding_tuple);
}

multi cont (Exception::Control::Next) {
...
}



-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me climbs a brick wall with his fingers: neeyah!



pgpiYc6duPVGk.pgp
Description: PGP signature


Re: Exceptuations

2005-09-27 Thread Nigel Hamilton

And handling user errors in a GUI application is a task for event handling,
*not* exception handling. I agree that both mechanisms share large parts
of the infra-structure supporting them. But I make a strong conceptual 
distinction between them.


Which leads to the question, does Perl6 have or need a build-in event
system on the language level?
--


Hear, hear.

Isn't just an exception a naughty event? But when you think about it, 
isn't all programming about suggesting events and handling what happens 
next?


Most of what a programmer does is suggest events to do (e.g., open file) 
and then handle the 'events' that happen next (e.g., file not found) and 
then suggest some more events (e.g., die). At the moment the programmer is 
the top-level event handler (e.g., damn - why didn't that work?) - but 
maybe some of this hassle could be handed off?


Is there a way to turn the exceptions type matching / depth finding 
problem inside out?


From the point of view of the operating system a program is a nasty 
exception to its normal running environment - your whole program is a kind 
of big exception!


Like someone intruding on a conversation the programmer tries to change 
the topic of the operating system. Hey can you get that network socket 
for me?


Programmers are constantly trying to change the topic of conversation of 
the operating system. Hey drop what you're doing. This is important. Get 
me that file.


But some of the nastiest (and exception raising) problems arise from the 
conversational disconnect between operating system and program (e.g., 
Sorry that port is blocked, Sorry can't find that file, Socket 
closed etc).


Is there a place in the room for a third party to the conversation? 
Somebody who could ...


Smooth over misunderstandings?
Do translation if either party doesn't understand?
Queue what should be the next topic of conversation?
Remember how topics are meant to be handled?
Provide a log of what was said?

Is there a way of integrating Perl's natural ability to stay on topic ($_) 
with exception handling, and event handling?


Just some thoughts ...

NIge


Re: Exceptuations

2005-09-27 Thread Yuval Kogman
On Tue, Sep 27, 2005 at 07:29:48 +0100, Nigel Hamilton wrote:
 And handling user errors in a GUI application is a task for event handling,
 *not* exception handling. I agree that both mechanisms share large parts
 of the infra-structure supporting them. But I make a strong conceptual 
 distinction between 
 them.
 Which leads to the question, does Perl6 have or need a build-in event
 system on the language level?

The exception mechanism is an event system that is typically used
for nothing but errors, but is much more extensible than that.

In fact, exceptions are nothing more than continuations really.

The CATCH block 'temp' sets a global exception handler continuation,
and die is simply

sub die (*$a) { *EXCEPTION_HANDLER.(*$@) }

Also, it's hard for a library writer to consistently decide what is
an error and what isn't. It's also too much trouble. If every
library had severity levels, things would be complicated for small
scripts.

On the other hand, whenever an event that is not what 90% of the
flow control should be does occur, exceptions let you delegate the
behavior of how to deal with this to other code, specifically the
code that called you.

It just happens that the default *EXCEPTION_HANDLER continuation is
essentially

print STDERR @_;
exit $bad_error_code;

 Hear, hear.
 
 Isn't just an exception a naughty event? But when you think about it, isn't 
 all programming 
 about suggesting events and handling what happens next?

Well, not necessarily. It's an event that is exceptional, i.e. not
normal.

99% of non normal events are errors, but we routinely use exceptions
for timeout, etc.

{
temp $SIG{ALRM} = { die timeout; } # we need a better 
mechanism for this in perl 6, IMHO

alarm 10;
connect(...);

CATCH {
when timeout {
$!.resume if prompt(The remote party does not 
seem to be responding. Keep trying?);
}

default { $!.rethrow }
}
}

Timing out is not an error unless the user decides it is. Normally
the user would have to decide beforehand when lack of responsiveness
becomes an error, but with a system like this the user can be
prompted on a case by case basis to decide whether it's an error or
not.

 Is there a way of integrating Perl's natural ability to stay on topic ($_) 
 with exception 
 handling, and event handling?

As I see it continuations are a way to get back on topic...

Hey, 3rd party, the underlying thingy told me that yadda
yadda... If you can fix it, here's what you do next.

This is why I proposed the idea.

I would like to expand on your ideas though - the program is layered
with a delegation hierarchy... The lowest level agent is the
operating system. On the other side, the user makes a query to the
program which makes a query to it's first level handler, that uses a
library, that uses another and so on and so forth.

In a sense, the third party you mention is always the caller of a
given block of code, with the other two parties being the called
level, and the level below it.

Intervention on behalf of the third party can be delegated upwards
if this layer does not have enough policy on event handling. The
only level which really knows how to behave under any event
(hopefully ;-) is the user.

 Just some thoughts ...

Good post!

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me does a karate-chop-flip: neeyah!!



pgpFk63eGjRwQ.pgp
Description: PGP signature


Re: Exceptuations

2005-09-27 Thread Ruud H.G. van Tol
Nigel Hamilton schreef:

 From the point of view of the operating system a program is a nasty
 exception to its normal running environment - your whole program is a
 kind of big exception!

As if a real OS really likes to run idle most of the time.
;)


 Like someone intruding on a conversation the programmer tries to
 change the topic of the operating system. Hey can you get that
 network socket for me?

 Programmers are constantly trying to change the topic of
 conversation of the operating system. Hey drop what you're doing.
 This is important. Get me that file.

Or the OS is more like a waiter, nervously circling the tables, watching
out for orders.


 Is there a way of integrating Perl's natural ability to stay on topic
 ($_) with exception handling, and event handling?

http://poe.perl.org/?POE_FAQ/Will_Perl_6_make_POE_obsolete


And how about agents and messages?

-- 
Grtz, Ruud



Re: Exceptuations

2005-09-26 Thread Piers Cawley
Luke Palmer [EMAIL PROTECTED] writes:

 On 9/25/05, Yuval Kogman [EMAIL PROTECTED] wrote:
 I propose a new model - each exception has a continuation that
 allows it to be unfatalized.

 I think we've already talked about something like this.  But in the
 presence of use fatal, it makes a lot more sense.

 Something comes to mind:

 use fatal;
 sub foo()  { bar()  }
 sub bar()  { baz()  }
 sub baz()  { quux() }
 sub quux() { fail }
 {
 say foo();
 CATCH { $!.continue(42) }
 }

 Exactly which exception is continued?

The bottommost one. If you want to return to somewhere up its call chain, do:

  $!.caller(n).continue(42)

Assuming caller returns a continuation (which I still fondly hope it will). I'm
assuming you're examples aren't necessarily tail calls of course. 


 Where do we cut off the call chain and replace our own value?  This comes up
 again with open().  Let's say open is implemented with a series of five
 nested calls, the innermost which knows how to fail and propagate outwards.
 However, the programmer using open() has no idea of its internals, so it
 ought to override the return value of open() itself, rather than its utility
 functions.  However, we can't go with outermost, because then you'd only be
 fixing the lexical call (say foo() above).  So it's somewhere in between.
 Where?

Obviously the topmost function should do:

  sub open(...) {
...
CATCH { $!.rethrow }
  }

This assumes that 'rethrow' throws a new exception that delegates to the
original exception for lots of its behaviour. If, later, you want to explicitly
get at the exception thrown by the helper function, you could do something
like:

   $!.inner

-- 
Piers Cawley [EMAIL PROTECTED]
http://www.bofh.org.uk/


Re: Exceptuations

2005-09-26 Thread TSa

HaloO,

Piers Cawley wrote:

Exactly which exception is continued?

The bottommost one. If you want to return to somewhere up its call chain, do:

  $!.caller(n).continue(42)


Whow, how does a higher level exception catcher *in general* know
what type it should return and how to construct it. The inocent foo()
caller shouldn't bother about a quux() somewhere down the line of
command. Much less of it innards.

Think of receiving a 'shelf picker died of lung cancer' exception
when you just ordered a book from your favorite book dealer. Irrespective
of the seriousness to the shelf picker, but how would you expect a customer
to handle such an exception?

To me exceptions are to be handled with respect to the service
the scope invoked. In my example I would conclude that the book dealer has
more than one shelf picker under contract and just re-issue the order.
Well, or buy it elsewhere. In other words if the task at hand is
buying a certain book, exception handling means iterating all viable
sources with the assumption that the most convenient one *usually* delivers.
Otherwise I would code an iteration over the sources right away.

And handling user errors in a GUI application is a task for event handling,
*not* exception handling. I agree that both mechanisms share large parts
of the infra-structure supporting them. But I make a strong conceptual 
distinction between them.


Which leads to the question, does Perl6 have or need a build-in event
system on the language level?
--
$TSa.greeting := HaloO; # mind the echo!


Re: Exceptuations

2005-09-26 Thread Piers Cawley
TSa [EMAIL PROTECTED] writes:

 HaloO,

 Piers Cawley wrote:
Exactly which exception is continued?
 The bottommost one. If you want to return to somewhere up its call chain, do:
   $!.caller(n).continue(42)

 Whow, how does a higher level exception catcher *in general* know
 what type it should return and how to construct it.

It asks the continuation? The information should be there. Consider a function
definition:

  sub whatever(...) returns List {
throw ResumableException;
  }

Then, assuming that caller returns continuation -- which is a pretty big
assumption, but which would be really cool -- $!.caller(1) would be a
continuation with an signature of (List $not_a_real_name). If the function can
return several types dependent on context, then the continuation's signature
would be the appropriate one for the context in which the function was
called. Monkeying with this kind of thing in code isn't necessarily a good
idea, but it's great for, for instance, having a top level exception catcher
that could (potentially) bring up an interactive shell with limited debugging
features which would allow you to inspect the running program and work out what
went wrong. Ruby on Rails already does something like this, with the added
wrinkle that, if it hits a breakpoint when running in the server it hands off
the interactive session to a console process rather than having you monkey with
it within your browser. A very neat trick and a remarkably powerful debugging
technique. 


 The inocent foo() caller shouldn't bother about a quux() somewhere down the
 line of command. Much less of it innards.

 Think of receiving a 'shelf picker died of lung cancer' exception when you
 just ordered a book from your favorite book dealer. Irrespective of the
 seriousness to the shelf picker, but how would you expect a customer to
 handle such an exception?

I wouldn't, but I would expect that a programmer would find such an exception
very useful indeed.

-- 
Piers Cawley [EMAIL PROTECTED]
http://www.bofh.org.uk/


Re: Exceptuations

2005-09-26 Thread Yuval Kogman
On Mon, Sep 26, 2005 at 17:40:52 +0100, Piers Cawley wrote:
 Luke Palmer [EMAIL PROTECTED] writes:
 
  On 9/25/05, Yuval Kogman [EMAIL PROTECTED] wrote:
  I propose a new model - each exception has a continuation that
  allows it to be unfatalized.
 
  I think we've already talked about something like this.  But in the
  presence of use fatal, it makes a lot more sense.
 
  Something comes to mind:
 
  use fatal;
  sub foo()  { bar()  }
  sub bar()  { baz()  }
  sub baz()  { quux() }
  sub quux() { fail }
  {
  say foo();
  CATCH { $!.continue(42) }
  }
 
  Exactly which exception is continued?
 
 The bottommost one. If you want to return to somewhere up its call chain, do:
 
   $!.caller(n).continue(42)

This breaks encapsulation, like luqui mentioned.

However, since every exception has an exception stack, i guess you
could see exactly how it was propagated non-fatally, before it was
actually thrown.

   sub open(...) {
 ...
 CATCH { $!.rethrow }
   }
...
$!.inner


That way behavior like that could be automated

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me sushi-spin-kicks : neeyah



pgpz89jwQwGFi.pgp
Description: PGP signature


Exceptuations

2005-09-25 Thread Yuval Kogman
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


Re: Exceptuations

2005-09-25 Thread Yuval Kogman
In order to support continuable exception generators, here is a
style guide for exception values, and an observation on what
exceptions should support at the language level:

* Exceptions should preserve data

All exceptions should contain as much of the original data that
caused them...

With Luke's new theory proposal, storing the argument tuple for the
call the raised the exception is logical. For example, for a
Permission Denied error raised in open() we should have access to
the filename that we tried to open, and the mode we tried to open it
with.

* Each thrown exception should contain the value of $! from before
it was thrown

* Each thrown exception has to know whether it was thrown because of
'use fatal' or because of an explicit 'die'

* fail should be used except for very strict conditions

* use fatal should be encouraged by the documentation, for one
liners, scripts, and full blown apps.

* Context data should be overridable at the exception object level

Carp and friends should be implemented not by using a different
keyword than fail, but failing with a value that specifies a certain
context.

sub croak (*$a) { # tuples again
fail Exception.new(*$a, :position($?CALLER::CALLER::POSITION));
}

* fail should cascade such that every time a block is left with a
failing return value, the block's caller should be checked for use
fatal.

* When continuing into an exception, the parameters to the
continuation are substituted for the error.

use fatal;

my $value = {
fail foo;

CATCH {
$!.continue(bar);
}
}

say $bar;

Continuing into the exception with no arguments is like ignoring
'use fatal' for this specific exception, causing the failed value to
propagate out of the fatalized block.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me wields bonsai kittens: neeyah



pgpE7Wb5OOFbg.pgp
Description: PGP signature


Re: Exceptuations

2005-09-25 Thread Yuval Kogman
On Sun, Sep 25, 2005 at 18:11:22 +0300, Yuval Kogman wrote:
 In order to support continuable exception generators, here is a
 style guide for exception values, and an observation on what
 exceptions should support at the language level:

And more...

* Exception strings are for humans

Humans need to know what happened in their own words. They have a
hard time analyzing error codes, or constant names.

Computers have a hard time analyzing strings, and prefer hard data.

It should be easy to identify each error in a way that is meaningful
to computers, and this way should be orthogonal to the string that
is displayed to the user when possible.

This means that it should be incredibly easy for the user to declare
exception classes as they are used, perhaps by stealing goodness
from enumish constructs, or somesuch.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: *shu*rik*en*sh*u*rik*en*s*hur*i*ke*n*: neeyah



pgpcpkWrPtIwr.pgp
Description: PGP signature


Re: Exceptuations - CPS explained

2005-09-25 Thread Yuval Kogman
To ease the understanding of exactly how this might work, assume
that perl 6 is really all continuation passing style under the
surface (parrot is ;-).

use fatal;
my $x = do_bar();
do_foo();

sub do_bar {
fail bah;
}

The way CPS works is really simple. The principal is that there is
no concept of return. Instead, the call to do_bar, for example, gets
an additional implicit parameter. This parameter is the code ref to
the rest of the code, and could look something like this if
deparsed:

sub ($rv) {
my $x = $rv;
do_foo()
}

So do_bar knows to make a goto to that code ref with it's return
value.

Now, fail gets something similar - it gets the code ref which
applies do_bar's passed in code ref, and it applies it the exception
constructed from bah.

Fail will also check first to see if the continuation might, at some
level, use fatal. If it does, it takes a dynamically scoped value
instead - the continuation for the last encountered CATCH block.

When it throws the exception, fail will store the continuation it
got (the $x = ... stuff) in the exception object.

CATCH can then choose either to goto it's parent block's
continuation (exit normally), or to goto the continuation stored in
the exception object, which is indirectly the assignment to $x.

Autrijus's example makes this clear (he prefers resume over
continue):

use fatal;
my $x = { 1/0 * 3 CATCH { $!.resume(9) } }; # 27

What's happening is that infix:/ checks if it's divisor is 0,
and if it is, it will fail. Fail has a continuation to 'multiply by
3 - exit from block - assign to $x', and it stores that in the
exception object. Instead of gotoing to that continuation, it will
instead take the last CATCH block that was relevant, in this case
the only one. This one finds the continuation to * 3 etc in the
exception object, and effectively augments the result of
infix:/(1, 0) to be 9 instead of an undefined value.

I hope this makes things clear.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me does not drink tibetian laxative tea: neeyah!



pgpC58pLTHBic.pgp
Description: PGP signature


Re: Exceptuations

2005-09-25 Thread Luke Palmer
On 9/25/05, Yuval Kogman [EMAIL PROTECTED] wrote:
 I propose a new model - each exception has a continuation that
 allows it to be unfatalized.

I think we've already talked about something like this.  But in the
presence of use fatal, it makes a lot more sense.

Something comes to mind:

use fatal;
sub foo()  { bar()  }
sub bar()  { baz()  }
sub baz()  { quux() }
sub quux() { fail }
{
say foo();
CATCH { $!.continue(42) }
}

Exactly which exception is continued?  Where do we cut off the call
chain and replace our own value?  This comes up again with open(). 
Let's say open is implemented with a series of five nested calls, the
innermost which knows how to fail and propagate outwards.  However,
the programmer using open() has no idea of its internals, so it ought
to override the return value of open() itself, rather than its utility
functions.  However, we can't go with outermost, because then you'd
only be fixing the lexical call (say foo() above).  So it's
somewhere in between.  Where?

Luke


Re: Exceptuations

2005-09-25 Thread Michael Walter
On 9/25/05, Luke Palmer [EMAIL PROTECTED] wrote:
 [...]
 Exactly which exception is continued?
 [...]
Named restarts in Common Lisp appear to try to solve a related
problem, if I'm skimming this thread correctly. :-) (see [1]).

Michael

[1] 
http://www.supelec.fr/docs/cltl/clm/node312.html#SECTION00330


Re: Exceptuations

2005-09-25 Thread Yuval Kogman
On Sun, Sep 25, 2005 at 11:32:54 -0600, Luke Palmer wrote:

 Exactly which exception is continued?
...
 This comes up again with open().  So it's somewhere in between.
 Where?

For the open() example I don't have a solution but I know in what
direction to throw it: the same thing that makes croak appear to
work from the caller =)

Several things come to mind... First is this: (ugly)

sub open {
...
CATCH { fail $! }; # force it to go up
}

This is the most flexible, but also the crudest method.

Another idea is to use the same namespace hopping logic that Carp
does right now. This doesn't work for exceptions in the same class
so it should be optional and off by default... Perhaps:

fail error :package_boundry; # better word needed

Another idea is to use a lexical pragme that delays all errors,
which is like CATCH { fail $! } but more declarative:

sub open {
use fatal propagate;
...
}

For when it isn't specified, when doing evil things such as stepping
into the continuation of an exception, we assume that the code doing
the CATCH knows about the code that raised the exception at least
something.

Encapsulation is sort of maintained by specifying what kinds of
operations are fixed.. For example, errors having to do with opening
files are fixuppable by taking the arguments to open found in the
exception, and trying to reopen the file after some fudging, and
returning a handle. This is common knowlege about the interface of
open, and we are simply saying that for the rest of the dynamic
scope (dangerous, perhaps) we are trying to fixup every call to open
that fails with this handler.

This is no different than catching that exception in terms of
encapsulation, except that the failure is defatalized. My claim is
that just as you know the kind of error it is when you explicitly
catch it for the purpose of reporting, you have the same knowlege
when you are fixing.

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me sushi-spin-kicks : neeyah



pgpCOTXugoPT2.pgp
Description: PGP signature