[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Multiple values in Dylan



/// >From the point of view of readability, ignored extra value returns
/// >don't seem so bad.

I agree thoroughly.

/// Named returns could improve readability a lot.
/// 
/// Using #f to mean both boolean False and no-value seems error-prone; so
/// does letting anything that's not #f mean #t.  I know, it's a
/// long-standing Lisp tradition, but then so is () == #f, which Dylan
/// does fix.
///
/// This comes up when some of the additional value returns are booleans
/// which are only sometimes valid.  If you test them before checking
/// whether they're valid, you get misleading results.  For that matter,
/// you can't even use type checking if you believe that they're always
/// valid, since all values are legitimate booleans.  If in some
/// unexpected case they turn out not to be valid, an error won't be
/// signaled.

The same design-flaw exists in 'C' -- when a function returns a pointer, NULL
can be returned to signal an error.  Functions returning integers though have
no value that can be returned as 'not an integer.'

Having true error values can be (provided that method dispatch is modified
accordingly) a real benefit for readability's sake.  Errors are logically
checked by checking the return value of a function.  This way, all exceptional
cases are reported to the caller in the same way, rather than some as #f, some
as 0, some as -1, and some as requiring an exception handler to have been set
before calling the function in question.  Besides removing the idea of a non-
local GOTO from common (in my opinion _recoverable_) exception handling, it
can really get us out of some of the tight places we find ourselves when
discussing the correct behaviour of special forms... like bind.

/// So why not make #f and #t the only valid booleans, and reserve #none
/// for "invalid"?

I like this idea, but I'd want to extend it.  See the following proposal on
giving Dylan a value-oriented exception system.  (Yes, I know this is a little
tangental, but it really fits well in this context)  One of the things that
greatly impressed me about Dylan was that it was Object Oriented without
losing LISPs origional Value Orientation (as contrasted to FORTRAN [etc.]'s
Procedural Orientation).  The exception system currently in the Dylan spec,
though, seems to be inspired by procedure oriented programming languages.  It
was the one part of the language I was least impressed by.

///         -s
/// 

	-- Scot

------------------------------------------------------------------------------

Proposal:

	Add a built-in class <undefined> with two subclasses: <bottom> and
<top>.  All exception classes would belong to <undefined>.  #bottom would be
the only object that is a direct instance of <bottom>.  <bottom> should be
sealed, and <top> left open for user-defined exceptions.  <undefined> should
not inherit from <object> for reasons listed below:

As <top> is subclassed, additional slots may be added to carry information,
of course.  Like (define-class <file-not-found> (<top>)
			(file-name <string>)  ;; syntax may be wrong
			)
..for example.

Modifications to Method-Dispatch:
				(Why <undefined> should NOT inherit <object>)

When method dispatch is given an <undefined> parameter, it should consult
the methods within the generic function for methods working _without_ certain
values (e.g., methods whose corresponding parameter's class restriction(s)
inherit from <undefined> or are <undefined> themselves).  If no method can
be found, then the system should stop.  For this reason, methods should not
be considered part of <object>.  Otherwise, errors will cascade in
unpredictable, and unreasonable ways.

An alternate method dispatch scheme is to provide a <top> value from the
dispatcher, that would contain a slot for the <undefined> value for which
method-dispatch was unable to find an appropriate method.  This way, an
un-caught exception would fall through the initial function invocation of the
program, containing a detailed back-trace.  Since exceptions are, well,
exceptional, this performance hit really wouldn't be noticeable.  It also
provides a clear way to orderly exit from a program.  Note also that allowing
errors to 'cascade' thus provides a much more sane approach than if <undefined>
inheritted <object>, which would cause an _entire_ stack dump (mostly
irrelevant and confusing)

Also, an implementation of display/print (used in the read-eval-print loop)
should be provided allowing the developer to brouse through errors, so that
a back-trace doesn't simply fill the screen, scroll off, force the offending
code out of the text-buffer being worked with, etc.

It would probably be best for implementations to provide both of these
features as options.  Also, NB that <undefined>, renamed to <error> could
continue to function as in the Dylan spec.  This would give language users the
choice of how to handle exceptions... With 'values' or with non-local flow of
control.