[comp.lang.scheme] open-input-file topics from hell, part 2

Alan@lcs.mit.EDU (Alan Bawden) (04/22/91)

   Date: 20 Apr 91 04:41:33 GMT
   From: david carlton <carlton@husc10.harvard.edu>

   3) Have open-{input,output}-file return #f if the file doesn't exist.

[ I presume you don't really want open-output-file to return #f if the file
  doesn't exist! ]

   Currently, implementations are forced to signal an error in such a
   situation, which is ridiculous, since it makes it impossible to handle
   that situation, which is a fairly common one.

I agree that it is ridiculous that there isn't a way to handle that
situation.  But having open-input-file return #F isn't the solution.  For
one thing, inexperienced programmers would frequently forget to check the
return value.  

Also, you really do need finer control of exceptions.  People write
programs that need to distinguish between:

  o  The file does not exist in the specified directory.
  o  Some directory in the specified path does not exist.
  o  The file exists, but you aren't allowed to read it.
  o  You aren't allowed to read some directory in the specified path.
  o  The filesystem containing the file is unavailable (perhaps due to
     network lossage).

And for open-output-file things are worse because it involves possible
mutation of the filesystem.

I think ultimate solution is to have a condition system that can handle
exceptional conditions.  This may be another one of those things that you
can't really do until you have a coherent story to tell about dynamic
binding.  So forget the ultimate solution.

So how about giving open-input-file some additional arguments that specify
how it should behave in the exceptional cases?  Like an a-list of
"exceptions" and associated thunks -- if any of the exceptions occurs, the
associated thunk is (tail-recursively) invoked.  

This isn't a serious proposal, but something like it is clearly preferable
to the oft-suggested horror of simply having open-...-file return #F if
some ill-specified set of things go wrong.

Alan@lcs.mit.EDU (Alan Bawden) (04/23/91)

   Date: Sun, 21 Apr 91 20:10:47 pdt
   From: Roger Nelson - Grad Student <rnelson@eecs.wsu.edu>
   ...
   What would be wrong with the open file functions simply returing an error
   code rather than a port or #f in the event of an open error.
   ...

As I said before, what's wrong with this is that people will write programs
that forget to check the return value.  I've been there.  This is exactly
the way the early Lisp Machine system handled file open errors, and it was
a total pain.  The problem is that you -always- have to check the return
value before you can start using it as a port, so the return value
overloading gains you nothing.

In the case where you care to handle errors, you are necessarily going to
be engaging in control structure, so passing alternate continuations to the
file opening procedures seems like the perfect solution.

matthias@leto.rice.edu (Matthias Felleisen) (04/23/91)

In article <9104221752.AA00289@august> Alan@lcs.mit.EDU (Alan Bawden) writes:
>   From: Roger Nelson - Grad Student <rnelson@eecs.wsu.edu>
>   What would be wrong with the open file functions simply returing an error
>   code rather than a port or #f in the event of an open error.
>As I said before, what's wrong with this is that people will write programs
>that forget to check the return value.  I've been there.  

I agree, but why not invoke ERROR or some CONTINUATION object and
provide a facility that intercepts such control actions  :-) ? 

-- Matthias

carlton@scws1.harvard.edu (david carlton) (04/24/91)

In article <9104211907.AA25632@august> Alan@lcs.mit.EDU (Alan Bawden) writes:
      From: david carlton <carlton@husc10.harvard.edu>

      3) Have open-{input,output}-file return #f if the file doesn't exist.

   [ I presume you don't really want open-output-file to return #f if the file
     doesn't exist! ]

You presume quite correctly, of course.

      Currently, implementations are forced to signal an error in such a
      situation, which is ridiculous, since it makes it impossible to handle
      that situation, which is a fairly common one.

   I agree that it is ridiculous that there isn't a way to handle that
   situation.  But having open-input-file return #F isn't the solution.  For
   one thing, inexperienced programmers would frequently forget to check the
   return value.  

I'm not sure that that's any worse than the current solution - the
program simply crashes in a different place.

   Also, you really do need finer control of exceptions.  People write
   programs that need to distinguish between:

     o  The file does not exist in the specified directory.
     o  Some directory in the specified path does not exist.
     o  The file exists, but you aren't allowed to read it.
     o  You aren't allowed to read some directory in the specified path.
     o  The filesystem containing the file is unavailable (perhaps due to
	network lossage).

   And for open-output-file things are worse because it involves possible
   mutation of the filesystem.

   I think ultimate solution is to have a condition system that can handle
   exceptional conditions.  This may be another one of those things that you
   can't really do until you have a coherent story to tell about dynamic
   binding.  So forget the ultimate solution.

   So how about giving open-input-file some additional arguments that specify
   how it should behave in the exceptional cases?  Like an a-list of
   "exceptions" and associated thunks -- if any of the exceptions occurs, the
   associated thunk is (tail-recursively) invoked.  

   This isn't a serious proposal, but something like it is clearly preferable
   to the oft-suggested horror of simply having open-...-file return #F if
   some ill-specified set of things go wrong.

Horror?  Good grief...  But I do agree that finer control over such
matters is preferable.  I don't think that taking care of it with an
exception mechanism is the right way to do this - I would much rather
write code that looks like

(let ((port (open-input-port filename)))
  (if (not port)
      (do-something)
      (proceed-with-one's-business)))

rather than

(let ((port (begin (install-exception-handler-to-do-something))
                   (open-input-port filename)))
  (proceed-with-one's-business))

Matter of taste, I suppose, but I would rather reserve exception
handlers for unexpected sorts of circumstances that programs normally
would die on, such as functions being applied to arguments of the
wrong type or the user hitting the interrupt key, rather than what I
think is probably a fairly common circumstance and one which any
program that does I/O should be prepared to handle, namely the
non-existence of files.

So what would I propose?  In its context, I think that the C/UNIX way
of doing things, with functions that return some sort of distinctive
value, typically 0 or -1, to signal an error, and then set the value
of the global variable errno to be equal to a more informative message
for the use of the programs that care about those details.  But that
doesn't strike me as particularly Schemey.  Another suggestion would
be to have the functions return one of a set of distinctive objects if
the open failed.  What those distinctive objects should be is another
matter - I think that I would lean towards creating a whole new type
of error-objects, but doubtless many people would disagree with me.
Symbols would probably work - easy to check for equality (not that
speed is of primary importance in error handling, but it doesn't
hurt), and it's easier to have the symbol store useful information
than it would be if the error return value were a number.  Yet another
possibility would be to have the file return two arguments in an error
condition, the first being #f and the second being something more
informative.  Of course, this would only work if multiple return
values were implemented a la Common Lisp, something which I don't
really like, but this would seem (to me, at any rate) to be a natural
situation to use that.  That way, people could ignore the second
argument if they didn't care about why their open-input-file didn't
work, but would have the extra information there if they wanted it.

To be sure, none of my suggestions solve your complaint that people
don't check the return value.  As I said above, I don't think that
this is a big problem - the program will simply crash in a different
place, and while it may produce a less intuitive error message the
result is still the same.  And I'm not a big fan of designing
languages to help the "inexperienced programmers" who "would
frequently forget to check the return value" - they can learn.  In
this case, admittedly, things are different since code written to
follow the current standard couldn't check the return value if it
wanted to, but, after all, introducing incompatibilities in Scheme
standards is a time-honoured tradition :-)

jaffer@zurich.ai.mit.edu (Aubrey Jaffer) (04/24/91)

How about this as a solution:

The open-xxx functions would return special ports if the file could
not be opened.  These special ports all have reached end-of-file or
are closed (I am not sure which is better).  These special ports are
the value of the symbols:
        file-does-not-exist
        path-does-not-exist
        insufficient-priveledge-to-access-file
        insufficient-priveledge-to-access-path
        file-system-unavailable

The error conditions can be checked for by (eq? file-does-not-exist port)
and so on.

This plan has the open functions always returning a port and allows
those who want to check to do so.  For those who don't check
end-of-files await.

jinx@zurich.ai.mit.edu (Guillermo J. Rozas) (04/24/91)

    Horror?  Good grief...  But I do agree that finer control over such
    matters is preferable.  I don't think that taking care of it with an
    exception mechanism is the right way to do this - I would much rather
    write code that looks like

    (let ((port (open-input-port filename)))
      (if (not port)
	  (do-something)
	  (proceed-with-one's-business)))

    rather than

    (let ((port (begin (install-exception-handler-to-do-something))
		       (open-input-port filename)))
      (proceed-with-one's-business))

    Matter of taste, I suppose, but I would rather reserve exception
    handlers for unexpected sorts of circumstances that programs normally
    would die on, such as functions being applied to arguments of the
    wrong type or the user hitting the interrupt key, rather than what I
    think is probably a fairly common circumstance and one which any
    program that does I/O should be prepared to handle, namely the
    non-existence of files.

The non-existence of an expected file sounds like an unexpected sort
of circumstance to me. :-)

Clearly both solutions are equipotent.  Given control over exceptions,
you can

(define (my-open-input-port filename)
  (install-exception-handler-return-false)
  (open-input-port filename))

although install-exception-handler would probably be a wrapper to
limit the extent of the action.
The converse is straightforward.

The language could choose either mechanism and you could use whichever
one you preferred in your code.

Personally, I am tired of fixing C programs that do not check the
return status of system calls and fail with segmentation violations
later on.  To avoid having the same thing happen in Scheme, I'd much
rather have Scheme's primitives error, and have a reasonable condition
system that allows me to handle those errors when needed.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (04/24/91)

I note that Common Lisp has (CLtL 2nd ed, p646)
	(open filename &key :direction :element-type :external-format
		:if-exists :if-does-not-exist)
:direction can be
	:input		like (open-input-file filename)
	:output		like (open-output-file filename)
	:io		-- no equivalent
	:probe		like (file-exists? filename)
:if-exists is used for :direction :output or :io and can be
	:error		signal error if the file exists
	:new-version	make a new version
	:rename		rename old file out of the way
	:rename-and-delete
	:overwrite	write on top of the old file
	:append		*NOT* the same as C's "append" mode
	:supersede	more or less the same as C's "write" mode.
	nil		return nil to indicate failure
:if-does-not-exist is used for all directions and can be
	:error		signal an error if the file does not exist
	:create		make an empty file and keep going
	nil		return nil to indicate failure.

I note that
	(open filename :direction :input :if-does-not-exist :create)
is a combination which no-one has suggested yet.
I further note that Common Lisp does _not_ provide any way of saying
"if the file _does_ exist but you aren't allowed to write on it or
rename it or delete it, do such-and-such".

The basic choice in each case is
	(return false, signal an error, handle the situation and continue)

It seems to me that the simplest and most "Scheme-like" approach is to add
an optional argument, whose value would be a function:
	(open-input-file filename [handler])
	(open-output-file filename [handler])
where the handler is a function of 2 arguments:
	-- a system-dependent code indicating the nature of the problem
	-- the filename after (system-dependent) expansion
and if the handler returns normally its value would become the value of
the call to open-input-stream.  The handler not being supplied, the
default would be to signal an error.  Someone who -wants- #f to be
returned has only to do
	(open-input-file filename (lambda (e n) #f))

There is something going on here which means that always signalling an
error and relying on an error handling system might not be the best idea,
and that is that this approach makes retrying easy.

	(open-input-file filename
	    (lambda (error-code truename)
		(format #t "~&Can't read ~A~%~
			      System error code ~A~%~
			      Please enter another name: "
			truename error-code)
		(open-input-file (read-string))))

The only Scheme implementation I actually understand is Elk, and it
would be very easy to add this to Elk.

I note that C's approach to error reporting (namely leaving an error
code lying around in a global variable) is extremely invonvenient:
there is *no* way that you can *trust* the value of that global variable.
This approach (the handler function receiving the error code) provides
a clean way of picking up the error code without relying on global
variables, and makes sense even if you are using engines and the like.
-- 
Bad things happen periodically, and they're going to happen to somebody.
Why not you?					-- John Allen Paulos.

net@opal.cs.tu-berlin.de (Oliver Laumann) (04/25/91)

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
> The only Scheme implementation I actually understand is Elk, and it
> would be very easy to add this to Elk.

In Elk one can easily write a function that calls open-input-file
with a file name and, if the file cannot be opened, invokes a
user-supplied error handler like this:

(define (open-input-file-with-error-handler file handler)
  (call/cc
    (lambda (return)
      (fluid-let
        ((error-handler (lambda args (apply handler return args))))
	   (open-input-file file)))))

In this example, the user-supplied error handler is invoked with a
continuation, which, when called, returns a value to the caller
of open-input-file-with-error-handler and an error message (a symbol
identifying the function that failed, a format string, and optional
arguments).

The function could be used like this:

(define (my-handler return . error-message)
  ;; do something (e.g. print error message)
  (return #f))

(let ((port (open-input-file-with-error-handler '/etc/passwd my-handler)))
  (case port
    (#f   ;; file could not be opened
    (else ;; do something with the port

In case the user-supplied error handler terminates normally, Elk would
invoke the standard error handler supplied by the top level (which
prints the error message in a standard way and resets to the top level).

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (04/26/91)

In article <JAFFER.91Apr23221610@kleph.ai.mit.edu>, jaffer@zurich.ai.mit.edu (Aubrey Jaffer) writes:
> How about this as a solution: [(open ...) return special ports]
> the value of the symbols:
>         file-does-not-exist
>         path-does-not-exist
>         insufficient-priveledge-to-access-file
>         insufficient-priveledge-to-access-path
>         file-system-unavailable

Unacceptable.  To start with, you've provided evidence that some people
can't spell the names (there is no "d" in "privilege").  To continue,
I can't figure out what "path-does-not-exist" means (does it mean
*directory* does not exist?).  And to finish, a quick "man open" on this
version of UNIX revealed TWENTY-THREE error cases, not 5, and that number
of error cases is just _tiny_ compared with some operating systems I've
used (that had Lisp on them).  Where, for example, have you provided for
the case "there is no space left on that device"?

Considering these points, we learn that
1) The set of error outcomes depends on the operating system
2) The set of error outcomes may be large
3) We should not have a large set of error names, a set which
   varies from system to system, polluting the global namespace.

An alternative in keeping with the spirit of this approach would be
to have a class of error objects, so that (open...) would return
either something satisfying port? or something satisfying error?,
and amongst the operations on error objects there might be an
error-name, so that instead of

> The error conditions can be checked for by (eq? file-does-not-exist port)

we might have
	(if (error? port)
	    (if (string-ci=? (error-name port) "ENOENT")
		...
This approach has the same advantage as returning #f, namely that
if you don't check you will still get an error report as soon as
you try to use an error object as a port.

But this begins to sound like the Common Lisp condition system.

-- 
Bad things happen periodically, and they're going to happen to somebody.
Why not you?					-- John Allen Paulos.

cph@altdorf.ai.mit.EDU (Chris Hanson) (04/27/91)

   Date: 26 Apr 91 05:01:29 GMT
   From: "Richard A. O'Keefe" <ok@goanna.cs.rmit.oz.au>

   But this begins to sound like the Common Lisp condition system.

I understand that Common Lisp bashing is a popular sport in the Scheme
community, and I often gladly participate in it, but in this case I
think it is misdirected.  Once a great deal of CL "style" is stripped
away, the underlying mechanism of the condition system is
exceptionally simple, even elegant, and in my opinion should be
seriously considered as a solution to this problem.

Basically, the condition system consists of typed records (condition)
whose types are a taxonomy of errors, plus named continuations
(restarts) and a means of dynamically binding restarts and condition
handlers.  There is a little more to it than that, but really not very
much.  Anyone who thinks the condition system is hairy and complicated
should study it more carefully, particularly ignoring all the macros,
keywords, overloading, and other things that make it Common Lispish.

I'm not going to argue why the CL condition system is a good solution
-- I think that KMP's text in CLtL2 does that well -- but I will say
that the idea of returning error objects rather than signalling them
is a bad one.  On the face of it, signalling seems more complicated,
because it involves dynamic binding and non-local effects.  But a
closer examination of the problem reveals that it is a simpler
solution.  Let's look at the file-opening example to see why.

The discussion so far has centered on what happens when the programmer
is opening a file and has some particular idea of how to recover if
the open fails.  In my experience, this is the exception rather than
the rule, so in effect this means that most file-opening code will
have to detect this error and signal it "by hand", where currently the
error is signalled "automatically".  This is the first problem:
returning an error object simplifies the unusual case at the expense
of the common one.

Another assumption is that the code that opens the file is a natural
place to detect and handle the error.  Again, in my experience, this
isn't the case.  Usually, the call to OPEN-{IN,OUT}PUT-FILE is not in
the same place as the handler.  When it isn't, returning an error
object requires that all the intermediate code must know about the
possibility for errors, and suitably pass the error object along to
the caller.  Often this "passing along" will affect the control
structure of the program, imposing otherwise unnecessary constraints.
This is the second problem: lots of code that isn't interested in the
error must now become aware of it.

In both of the cases that cause these problems, the approach of
signalling errors and catching those errors with dynamically bound
handlers is simpler.  Despite the seeming "non-local" nature of this
solution, in fact it is MORE "local", because only the code that cares
to handle the error needs to know anything about it.  All the other
code can ignore the error entirely.

The last problem with the "returning errors" proposal is that it is
inconsistent with existing practice.  Adopting such a solution would
force everyone to rewrite their code, and Scheme implementations that
supported it would not comply with the IEEE standard.  In contrast, a
CL-like condition system can be added without changing any code, and
is totally compatible with the standard.

harlan@copper.ucs.indiana.edu (Pete Harlan) (04/28/91)

cph@altdorf.ai.mit.EDU (Chris Hanson) writes:
 [...]
>Another assumption is that the code that opens the file is a natural
>place to detect and handle the error.  Again, in my experience, this
>isn't the case.  Usually, the call to OPEN-{IN,OUT}PUT-FILE is not in
>the same place as the handler.  When it isn't, returning an error
>object requires that all the intermediate code must know about the
>possibility for errors, and suitably pass the error object along to
>the caller.  Often this "passing along" will affect the control
>structure of the program, imposing otherwise unnecessary constraints.
>This is the second problem: lots of code that isn't interested in the
>error must now become aware of it.
 [...]

But that's what continuations are for, right?  You can easily write
your own 'open-{in,out}put' routine that escapes to your own
dynamically-maintained exception handler.  That's the way I typically
do it in C, using setjmp and longjmp.

Returning an error is conceptually simpler, I think.  I'd personally
like to see the routine take a success and failure continuation, but
the world seems to not want primitive Scheme procedures to take
continuations.

In any case, it is easy enough to roll your own nonlocal exiting
mechanism on file failures if you want.  You could equally easy to
implement the error-returning system on top of the system-enforced
nonlocal exit system, if that system gave the handler the continuation
to get back to the point of the file call, but the error-returning
system is simpler.

I dunno.

Pete Harlan
harlan@copper.ucs.indiana.edu

gateley@rice.edu (John Gateley) (04/28/91)

In article <9104270655.aa29839@mc.lcs.mit.edu> cph@altdorf.ai.mit.EDU (Chris Hanson) writes:

      Date: 26 Apr 91 05:01:29 GMT
      From: "Richard A. O'Keefe" <ok@goanna.cs.rmit.oz.au>

      But this begins to sound like the Common Lisp condition system.

   I understand that Common Lisp bashing is a popular sport in the Scheme
   community, and I often gladly participate in it, but in this case I
   think it is misdirected.  Once a great deal of CL "style" is stripped
   away, the underlying mechanism of the condition system is
   exceptionally simple, even elegant, and in my opinion should be
   seriously considered as a solution to this problem.


(Hi Chris)
Let me second Chris's opinion. While at TI I developed a condition
system which was simple enough to have a scheme feel to it, yet
powerful enough to support CL's condition system. Suprisingly enough,
it was just the core of the CL system stripped of all the bells and
whistles and it does seem to be an elegant solution to the problem.

John
gateley@rice.edu
--
"I've thought the thoughts of little children and the thoughts of men
 I've thought the thoughts of stupid people who have never been
 so much in love as they should be and got confused too easily
 to fall in love again." The Residents and Renaldo and the Loaf

carlton@husc10.harvard.edu (david carlton) (04/28/91)

In article <5405@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:

   But this begins to sound like the Common Lisp condition system.

Could someone please post a description of how Common Lisp handles
this?  I for one am not familiar with it, and would like to know
more...

david carlton
carlton@husc9.harvard.edu

mkatz@garlic.stanford.EDU (Morris Katz) (04/29/91)

If we ever get serious about adding a condition(error) system to scheme, I
would suggest that we go back and take another look at the one in CLU.  (I
believe that this system shares a lot of commonality with CL, but I am not a CL
hacker and so have relatively little knowledge of the CL condition system.)  I
can honestly say that the CLU condition system is the only one with which I
have a fair degree of familiarity that is not IMHO completely broken.  Some of
the features it includes which I consider important are
1)  Dynamically scoped error handlers
2)  The ability to specify handlers for any set of errors and allow others to
    propogate out to dynamically enclosing scopes.
3)  A choice of how to resume computation following the handling of an error.
4)  The ability to define new error types.

The one feature which it lacks and I would like to see is a concept os a
hierarchy of errors.  By this I mean that several errors should all be
definable as a subtype of another error.  A handler for the supertype could
then handle errors for all the subtypes.  The default handler which most
systems currently support that just prints an error message on the screen would
be the handler for the error type of which all other error types are a subtype.
--------------------
Morry Katz
katz@cs.stanford.edu
--------------------

markf@zurich.ai.mit.edu (Mark Friedman) (04/29/91)

In article <harlan.672776128@copper> harlan@copper.ucs.indiana.edu (Pete Harlan) writes:

   cph@altdorf.ai.mit.EDU (Chris Hanson) writes:
    [stuff in favor of a Common Lisp style condition system]

   Returning an error is conceptually simpler, I think.  

I don't agree. As Kent Pitman points out in CLTL2 we would like to
think of procedures as accepting certain sets of valid arguments. When
procedures return error objects, we sort of throw away this notion
because you're returning a value for all arguments.

I prefer the current situation of being able to say that a certain
procedure accepts arguments of a certain sort and signals an error if
the arguments are not valid. As Chris said, we can build a condition
system consistant with this. You are then free to handle the
conditions as you see fit (e.g. return some special error object).

Returning an error may be easier to implement and perhaps easier for a
naive user to understand, but conceptually it is not simpler. In fact
I think that it is paradoxical to say that a procedure return an error.

   I'd personally like to see the routine take a success and failure
   continuation, but the world seems to not want primitive Scheme
   procedures to take continuations.

But just about any procedure may have an error. Do you propose that
they all have explicit success and failure continuations. And what
about Alan Bawden's point about all the different types of errors.
Even if you don't accept that a single primitive procedure doesn't
have different types of errors, a single user defined procedure should
be able to handle the union of the errors of all the procedures it
calls. Should procedures have failure continuations for all those
errors. A top-level procedure for any interesting program would have
a zillion (at least) failure continuations.

In general, dynamically scoped variables are used to avoid this
problem of passing along arguments by procedures which aren't really
interested in them. Dynamically scoped condition handlers do the same
thing for failure continuations.

   In any case, it is easy enough to roll your own nonlocal exiting
   mechanism on file failures if you want.  You could equally easy to
   implement the error-returning system on top of the system-enforced
   nonlocal exit system, if that system gave the handler the continuation
   to get back to the point of the file call, but the error-returning
   system is simpler.

As I argued above, I think that you should start with the condition
system and build the error-returning system on top of that.

-Mark
--

Mark Friedman
MIT Artificial Intelligence Lab
545 Technology Sq.
Cambridge, Ma. 02139

markf@zurich.ai.mit.edu

barmar@think.com (Barry Margolin) (04/30/91)

In article <MARKF.91Apr29120734@montreux.ai.mit.edu> markf@zurich.ai.mit.edu writes:
>In article <harlan.672776128@copper> harlan@copper.ucs.indiana.edu (Pete Harlan) writes:
>   Returning an error is conceptually simpler, I think.  
>
>I don't agree.

I agree with Mark (but then I'm a known CL bigot).  Here's a very good
reason why returning errors is a bad rule: what does

	(make-error 'invalid-options <options>)

return to indicate that the options were invalid?
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

barmar@think.com (Barry Margolin) (04/30/91)

In article <9104291603.AA12211@garlic.Stanford.EDU> mkatz@garlic.stanford.EDU (Morris Katz) writes:
>If we ever get serious about adding a condition(error) system to scheme, I
>would suggest that we go back and take another look at the one in CLU.  (I
>believe that this system shares a lot of commonality with CL, but I am not a CL
>hacker and so have relatively little knowledge of the CL condition system.)

It sure does.  Combine the four features of the CLU condition system that
you described with the one feature you wished for an you have the CL
condition system.
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (05/01/91)

In article <9104270655.aa29839@mc.lcs.mit.edu>, cph@altdorf.ai.mit.EDU (Chris Hanson) writes:
>    Date: 26 Apr 91 05:01:29 GMT
>    From: "Richard A. O'Keefe" <ok@goanna.cs.rmit.oz.au>
> 
>    But this begins to sound like the Common Lisp condition system.
> 
> I understand that Common Lisp bashing is a popular sport in the Scheme
> community, and I often gladly participate in it, but in this case I
> think it is misdirected.  Once a great deal of CL "style" is stripped
> away, the underlying mechanism of the condition system is
> exceptionally simple, even elegant, and in my opinion should be
> seriously considered as a solution to this problem.

I have dealt with this in E-mail, and am diappointed to see it surface in
this group.  The claim that I was "bashing" Common Lisp is *FALSE* and is
a radical misreading both of what I intended and what I in fact wrote.
As I put it in E-mail, "the wicked flee when no-one is pursuing them";
to put it more strongly, such an extreme reaction to the mere mention
(intended approvingly!) of CL betrays a defensiveness which is not
consonant with whole-hearted admiration.

I note that Oaklisp (one of the Schemes I use) has a condition system
broadly similar to the CL one, and the MIT C Scheme has a condition
system broadly similar to the CL one, though I've not had the chance to
try it.

My point, to belabour the obvious, was that if we _want_ a condition system,
it would be a good idea to save ourselves much labour by looking at what has
already been done.  I went on to consider an approach that can be used in
the absence of a condition handling system, because that was the topic of
this thread.

-- 
Bad things happen periodically, and they're going to happen to somebody.
Why not you?					-- John Allen Paulos.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (05/01/91)

In article <9104291603.AA12211@garlic.Stanford.EDU>, mkatz@garlic.stanford.EDU (Morris Katz) writes:
> Some of the features it includes which I consider important are
> 1)  Dynamically scoped error handlers
> 2)  The ability to specify handlers for any set of errors and allow others to
>     propagate out to dynamically enclosing scopes.
> 3)  A choice of how to resume computation following the handling of an error.
> 4)  The ability to define new error types.
> The one feature which it lacks and I would like to see is a concept os a
> hierarchy of errors.

You have just described the CL condition system.
-- 
Bad things happen periodically, and they're going to happen to somebody.
Why not you?					-- John Allen Paulos.