(1) "Because the procedures of Scheme, unlike the functions of ML and
Haskell, accept multiple arguments and return multiple values, this
SRFI allows a Just or Right container to hold more than one object.
The specification presented here, therefore, differs in several ways
from its analogues in other languages."
Here, "Left container" seems to be missing among "Just or Right
You may want to replace "more than one object" with "more than one
object or no object".
(2) It may make sense to add a linear update procedure `either-swap!'.
I don't see the point, given that Lefts and Rights are typically implemented as small fixed-size objects.
(3) Are there any guarantees stated in the actual specification that
the "types" defined in this SRFI are disjoint to other Scheme types.
I've added "disjoint from each other and all other types", which is a dangling reference we won't be able to fix until late in the process when we have a comprehensive list of SRFIs and types. I'm not concerned about this sort of language until then.
(4) Do we really want to restrict `equal' to an equivalence predicate
in procedures like `maybe=' or `either='? A predicate like ´<' would
also have its use cases. For that, the order of the arguments has to
be specified, of course.
(5) As discussed in another thread with Shiro, the default argument to
`failure' in `maybe-ref' can be made implementation-specific and
SHOULD default to a procedure that raises an error.
No, I want this to be an error that can be specifically detected.
(6) For clarification, the introductory paragraph under "Sequence
Operations" may go into the rationale (as well).
It applies only to that section, so I see no reason to move or copy it.
(7) `pred' and `success' are currently defined to "accept one or more
arguments". This has to be corrected into "accept zero or more
arguments" to handle Justs, Lefts and Rights whose payload has the
shape of zero values correctly.
(8) What is the logical meaning of `proc' and `mproc' not accepting
arguments wrapped into containers? This cannot be meant literally. It
is probably better to just remove that clause.
(9) `either-filter' and `either-remove' should take multiple obj
arguments (including) for consistency and regularity. The same goes
(10) `maybe-sequence' and `either-sequence' take a `traversable'
argument, but this kind of object seems to be not specified. Why do we
restrict `map' to just one argument,
Because map functions that take multiple arguments are designed to process multiple traversables. It would be confusing if the standard map, vector-map, etc. procedures were not acceptable as values of the map argument.
shan't we allow an arbitrary
number of arguments and get rid of `aggregator' this way?
The purpose of the aggregator argument is to reify the multiple values of the maybes/eithers so that they can be passed to map, one aggregate per element of the traversable.
(11) The example to `either-sequence' uses the `identity' procedure.
This procedure is called `values' in Scheme (one SRFI, namely SRFI 41,
mentions a procedure named `identity', but it doesn't seem to be part
of SRFI 41's interface).
Changed to (lambda (x) x).
(12) `maybe->either' and `either->maybe' speak of "the same payload in
the sense of eqv?".d
Changed to speak of "payload objects" instead.
Changed maybe= and either= to speak of "their respective payload objects" (which implies that the number of such objects is the same).
apply to the wording of, say, `either-swap' as well.
Changed in the same way.
(13) Please, please, reconsider the specification of `maybe->list' and
`either->list'. It would be much more regular and helpful if these
procedures returned #f in case of a Nothing (instead of the empty
list) and, by regularity, in case of a Left as well. In Scheme, nil is
a different value than false. Let's make use of this advantage!
I think it is more important that ->list functions always return a list, even though the distinction between Just no values and Nothing (and likewise for Either) is lost. Conversion functions are often lossy.
I have added list->left.
(14) The problem with the maybe->values/value->maybe and
either->values/values->either procedures is that they do not really
set up a bijection.
Another lossy protocol, yes. If you want to guarantee no lossage, stick with the original Maybe or Either.
(15) For consistency and regularity, `values->either' should accept an
arbitrary number of objs (including zero). The same is true for
The idea here is that you have a procedure that returns multiple values and you want to wrap it so it returns a container instead. If the multipel had to be passed as arguments, it would be necessary to reify them as a list and then to apply the appropriate constructor. By taking the procedure directly as an argument, this code can be provided once and for all inside values->maybe/either.
(16) The `producer' protocol used in `values->maybe' and
`values->either' (the same as in `call-with-values') make the job of
an optimizing compiler unnecessarily hard (). If `values->maybe'
and `values->either' were syntax, it would be a lot easier.
Unfortunately the forthcoming multiple values SRFI is not yet ready;
otherwise, we might reuse some of its idioms.
I'll wait on that, then. SRFI numbers are cheap.
(17) `lisp-values->maybe' and `lisp-values->either' have the same
problem as maybe->values/either->values in that zero values are
conflated/confused with Just/Right payloads consisting of zero values,
I've gotten rid of lisp-values<->either. So since maybe->lisp-values takes a Maybe and return exactly 2 values, the producer argument likewise produces two values and returns a Maybe.
(18) That the `successor' argument in `maybe-unfold' and
`either-unfold' is not being used smells a bit [can one say so in an
analog of "code smell"?]. The two procedures would be regular with
respect to the various unfold procedures in R7RS-large if, after the
seeds are stored as a payload, the successor is called on the seeds
and if the stop procedure then doesn't yield #f on the resulting
Here's the recursion of unfold from SRFI 1, with the arguments renamed:
(unfold stop? mapper successor seed &optional tail-gen) =
(if (stop? seed) (tail-gen seed)
(cons (mapper seed)
(unfold stop? mapper successor (successor seed))))
As you can see, stop? is the first procedure to be called.
(19) I still think that it is an error that the error MUST be
signaled. I still propose to change the wording so that an error
SHOULD be signaled ("encouraged" in the RNRS terminology) as this
would not preclude Schemes offering a fast unsafe execution mode.
The point is that the default version of maybe-ref should always raise a non-resumable exception whenever there is a Nothing; that way, one may safely unpack Maybes with a guarantee that the procedure which does so will terminate abnormally.
(20) What about a `maybe-case' as well? In `maybe-if', the payload of
the Just is thrown away, which is not what we always want.
(syntax-rules (just nothing)
((maybe-case e ((just . arg*) . body1) ((nothing) . body2))
(maybe-ref e (lambda () . body2) (lambda arg* body1)))))
A similar definition can be made for `either-case'.
Can you explain the purpose of this?