Moreover, the special form seems to be much more convenient for most
use cases/users. If Scheme were really a simplistic language, not even
'if' would be a special form but would take two thunks for the
consequent and the alternate.
This is actually true of Smalltalk, which I don't think could rightly be called simplistic. The reason it works is that in class True the :if:then message evaluates the consequent and returns the value, whereas in class False the opposite is true. (Of course, conditionals are necessary under the covers in order to do message dispatching at all, but this is invisible to Smalltalk users.) In any case, compilers have no trouble optimizing these messages into jumps. (Older Smalltalk implementations will malfunction if the :if:then message is sent to any other objects, but this is a bug.)
Unrelated to this, I still consider the name 'exception->either' a bad
grammatical abuse of the informal language by which we name
identifiers. The name would be good for a procedure taking exception
object (like R6RS's condition objects or Java's exception objects)
"Condition object" is the standard terminology in all Lisp environments; your argument would be strong if that were not the case. The term "exception" I use as a shorthand for "exceptional situation", where "situation" is an informally defined term.
taking their payload and wrapping them in an Either. In our case,
however, we are not even remotely just transforming data. We are
changing the control flow.
The whole section is called "Protocol conversions", so none of its members are primarily intended to transform data, though they often do so in fact. What we are converting from here is exceptional-situation protocol to Either protocol.
Don't use 'with-exception-handler'. Use 'guard', which is fool-proof.
For non-continuable exceptions, the exception handler of
'with-exception-handler' mustn't return (or another exception is
raised). So your code never yields '(left e)' to the enclosing
continuation.
You're right, of course. It needs a one-shot call/cc to break out of the handler.
The following version should work (apart from the bad name and apart
from that I still think a syntactic form is superior):
(define (exception->either pred thunk)
(guard (e ((pred e) (left e))) (right (thunk))))
I think you need an `else` there, but otherwise this looks good.
There's no much point in catching a programmer's
error with 'guard' or 'with-exception-handler' as no one expects such
an error being triggered in a correct program.
As I've pointed out, there is very often a need to continue operation even of a buggy program.
We really want something roughly like C's assert semantics here, which
is what happens in the rest of the language.
Same point: assert() conditionally calls abort(), and although it is possible to recover from abort() in Posix C, this is not true of ISO C.
'maybe-if' is
not much different to 'cond': It is a special form taking an argument,
which must evaluate to an object of a specific type (procedure or
Maybe).
That sounds compelling, but I don't think it is.
Now with your specification, the implementation's optimizer cannot
assume that 'bla' is a Maybe because there will be an observable side
effect when 'bla' is not a Maybe.
That's true too. But under the "is an error" semantics, the simplest implementation of (maybe-if m j n) is (if (just? m) j n), just as is given in the SRFI. In this case, since it is not an error to apply `just?` to a random object, n will be evaluated and its value returned. I submit that it is unacceptable behavior to silently swallow the difference between Nothing and a non-Maybe. Signaling an error that satisfies `error-object?` prevents this from happening unless an exception handler to that effect is explicitly installed.
John Cowan
http://vrici.lojban.org/~cowan xxxxxx@ccil.orgA poetical purist named Cowan [that's me]
Once put the rest of us dowan. [on xml-dev]
"Your verse would be sweeter / If it only had metre
And rhymes that didn't force me to frowan." [overpacked line!] --Michael Kay