srfi.189
- Maybe and Either: optional container types ¶Maybe and Either types are immutable container types that can “wrap” zero or more values. Maybe can be used in the context where the value(s) may be missing (as opposed to “zero values”). Either can be used in the context where the value(s) can be correct ones or erroneous ones.
If you’re familiar with functional languages like Haskell, you may already know them. They are useful when used in the monadic pattern; that is, you can code as if the chain of calculations never fails, yet whenever the calculation fail at one place, the rest of chain is canceled and just the failure is returned.
Maybe is a union of two types, Just and Nothing. Just wraps valid value(s), while Nothing indicates there’s no meaningful values. Either is a union of two types, Right and Left. Right wraps valid value(s), while Left indicates an error, carrying some information as its payload.
{srfi.189
}
Maybe classes. <just>
and <nothing>
are subclasses of
<maybe>
. An instance of <just>
carries zero or more
values (payload), while an instance of <nothing>
doesn’t carry
information.
The <maybe>
class is an abstract class and can’t
create an instance of its own.
Instances of <just>
and <nothing>
should be created with
constructor procedures just
and nothing
.
{srfi.189
}
Either classes. <right>
and <left>
are subclasses of
<either>
. An instance of either class carry zero or more
values (payload); it is customary to use <right>
to propagate
the legitimate results of compuation, while use <left>
to
propagate erroneous conditions whose payload describes what’s wrong.
The <either>
class is an abstract class and can’t
create an instance of its own.
Instances of <right>
and <left>
should be created with
constructor procedures right
and left
.
[SRFI-189]{srfi.189
}
Type predicates.
Returns #t
iff obj is a Maybe, a Just, or a Nothing,
respectively.
[SRFI-189]{srfi.189
}
Type predicates.
Returns #t
iff obj is a Either, a Right, or a Left,
respectively.
[SRFI-189]{srfi.189
}
Equality predicate of Maybes. It returns #t
iff
all of maybe1 maybe … are Nothings,
or Justs with their respective payload objects are the same
using elt=.
[SRFI-189]{srfi.189
}
Equality predicate of Eithers. It returns #t
iff
all of either11 either … are the same
types (all Rights, or all Lefts), with
respective payload objects are the same
using elt=.
[SRFI-189]{srfi.189
}
Returns a Just with obj … as its payload.
[SRFI-189]{srfi.189
}
Returns a Nothing.
[SRFI-189]{srfi.189
}
Returns a Right or a Left respectively, with obj …
as its payload.
[SRFI-189]{srfi.189
}
Returns a Just, Right or Left respectively, with
objs as its payload.
[SRFI-189]{srfi.189
}
The maybe argument must be a Maybe.
If it is a Just, then a Right with the same payload is returned.
If it is a Nothing, a Left with obj … as its payload.
[SRFI-189]{srfi.189
}
The either argument must be an Either.
If it is a Right, then a Just with the same payload is returned.
If it is a Left, a Nothing is returned.
[SRFI-189]{srfi.189
}
The either argument must be an Either.
If it is a Right, a Left with the same payload argument is returned.
If it is a Left, a Right with the same payload argument is returned.
[SRFI-189]{srfi.189
}
The maybe arugment must be a Maybe. If it’s a Nothing,
a procedure failure is tail-called with no arguments.
If it’s Just, a procedure success is tail-called with its
payload object(s). If success is omitted, values
is used.
(maybe-ref (just 1 2) (^[] (error 'huh?)) +) ⇒ 3
[SRFI-189]{srfi.189
}
The either argument must be an Either.
If it’s a Left, a procedure failure is called with
its payload object(s). If it’s a Right, a procedure
success is called with its payload object(s).
If success is omitted, values
is used.
[SRFI-189]{srfi.189
}
The maybe argument must be a Maybe. If it’s a Nothing,
default … are returned as multiple values.
If it’s a Just, its payload object(s) is/are returned as multiple values.
[SRFI-189]{srfi.189
}
The either argument must be an Either. If it’s a Left,
default … are returned as multiple values (the Left’s payload
is discarded).
If it’s a Right, its payload object(s) is/are returned as multiple values.
[SRFI-189]{srfi.189
}
If maybe is a Nothing,
it is returned. If it’s a Maybe and its only payload is a Maybe,
the inner Maybe is returned. Other cases raise an error.
[SRFI-189]{srfi.189
}
If either is a Left, it is returned.
If it is a Right and its only payload is an Either,
the inner Either is returned. Other cases raise an error.
[SRFI-189]{srfi.189
}
Monadic bind operation. The maybe argument must be a Maybe.
If it is a Nothing, it is returned.
If it is a Just, its payload object(s) is/are applied to a procedure
mproc, which must return a Maybe. If mproc2 … are
given, the same operation is repeated on them.
(maybe-bind m p p2) ≡ (maybe-bind (maybe-bind m p) p2)
[SRFI-189]{srfi.189
}
Monadic bind operation. The either argument must be an Either.
If it is a Left, it is returned as is.
If it is a Right, its payload object(s) is/are applied to a procedure
mproc, which must return an Either. If mproc2 … are
given, the same operation is repeated on them.
(either-bind e p p2) ≡ (either-bind (either-bind e p) p2)
[SRFI-189]{srfi.189
}
Each argument must be a procedure taking zero or more arguments
and return a Maybe/an Either. Returns a procedure that accepts zero or more
arguments and returns a Maybe/an Either.
When the returned procedure is called, it first calls mproc; if it returns a Nothing/Left, or there’s no more mprocs, the result is returned. If the result is a Just, its payload is applied to the next mproc, and so on.
(maybe-bind m p p2 ...) ⇒ (maybe-ref m (^[] (nothing)) (maybe-compose p p2 ...))
A Maybe and an Either can be a container of zero or one element, and we have several procedures that employ this view. (Note: For this purpose, we treat multiple payload values as a whole, since they are processed in one step—as if we don’t regard multiple procedure arguments and multiple return values as a sequence of individual values.)
[SRFI-189]{srfi.189
}
Returns 0 if maybe/either is a Nothing/Left, and
1 if it is a Just/Right. An error is thrown if the argument
isn’t a Maybe/an Either.
[SRFI-189]{srfi.189
}
If maybe/either is a Nothing/Left,
returns a Nothing/a Left of obj ….
If maybe/either is a Just/a Right, apply pred on
its payload value(s). If pred returns a true value,
maybe/either is returned; otherwise,
a Nothing/a Left of obj … is returned.
An error is thrown if maybe/either isn’t a Maybe/an Either.
[SRFI-189]{srfi.189
}
Like maybe-filter
/either-filter
, but the meaning of
pred is reversed.
[SRFI-189]{srfi.189
}
This converts a collection of Maybes/Eithers to a Mayber/an Either of
a collection. The input collection and the collection in the output can
be of different type.
It’s easier to explain using Haskell-ish type signatures, although
it’s not precisely specified. Suppose Container x
is
some kind of a collection of
type x, and a*
is multiple values of arbitrary types.
Mappable = Container Maybe a* CMap = ((Maybe a* -> b) -> Container Maybe a* -> Container' b Aggregator = a* -> b maybe-sequence :: Mappable -> CMap -> Aggregator -> Container' b
The cmap maps proc over the input container (mappable),
and gathers the result into another container. It can be any containers,
as long as it matches the mappable argument. For example, mappable
may be a vector of Maybes, and cmap can be vector-map
–in that case,
both Container
and Container'
are Vector
.
Or, mappable may be a list of Maybes, and cmap can be
(cut map-to <string> <> <>)
, then Container
is a list and
Container'
is a string.
The types a*
and b
is determined by the aggregator
procedure, whose default value is list
.
[SRFI-189]{srfi.189
}
If maybe/either is a Nothing/Left, it is returned as is.
If it is a Just/Right, its payload value(s) is/are passed to proc,
and the result is returned.
[SRFI-189]{srfi.189
}
If maybe/either is a Nothing/Left, these procedures do nothing.
Otherwise, proc is applied to the argument’s payload values.
The result of proc is discarded. Returns an unspecified vlaue.
[SRFI-189]{srfi.189
}
If maybe/either is a Nothing/Left, knil is returned.
Otherwise, kons is called with the argument’s payload values, plus
knil. What kons returns becomes the result.
[SRFI-189]{srfi.189
}
First, the stop predicate p is applied to seed ….
If it returns a true value, a Nothing / a Left of seed … is
returned. Otherwise, g is applied to seed …,
which should return the same number of values as seeds, and passed
to p. If p returns false, it is an error.
If p returns true, mapper is applied to seed …,
then the results are wrapped in a Just/Right to be returned.
[SRFI-189]{srfi.189
}
If maybe is a Just, returns a list of its payload values.
If it is a Nothing, an empty list is retured.
[SRFI-189]{srfi.189
}
If lis is an empty list, a Nothing is returned.
Otherwise, a Just that has elements in lis as payload values
is returned.
Note that (list->maybe (maybe->list x))
isn’t an identity
mapping—if x is a Just with zero payload values, you’ll get
a Nothing.
[SRFI-189]{srfi.189
}
If either is a Right, returns a list of its payload values.
If it is a Left, returns an empty string.
[SRFI-189]{srfi.189
}
If lis is an empty list, a Left of obj … is returned.
Otherwise, a Right that has elements in lis as payload values
is returned.
[SRFI-189]{srfi.189
}
If maybe is a Nothing, #f
is returned.
Otherwise, it must be a Just with one value, and its value is returned.
If maybe is a Just and it doesn’t have exactly one value, an error
is thrown. If you want to deal with arbitrary number of payload values,
use maybe->list-truth
.
[SRFI-189]{srfi.189
}
If obj is #f
, returns a Nothing.
Otherwise, returns a Just with obj as its payload.
Note that (truth->maybe (maybe->truth x))
isn’t an identity mapping—
if x is a Just wrapping #f
, you’ll get a Nothing.
[SRFI-189]{srfi.189
}
If either is a Left, #f
is returned.
Otherwise, it must be a Right with one value, and its value is returned.
If either is a Right and it doesn’t have exactly one value, an error
is thrown. If you want to deal with arbitrary number of payload values,
use either->list-truth
.
[SRFI-189]{srfi.189
}
If obj is #f
, returns a Left with fail-obj … is
returned.
Otherwise, returns a Right with obj as its payload.
[SRFI-189]{srfi.189
}
Like maybe->list
, it returns #f
if maybe is a Nothing.
If maybe is a Just, however, it returns a list of its payload values.
[SRFI-189]{srfi.189
}
The argument must be #f
of a list. If it is #f
, a Nothing
is returned. If it is a list, a Just with elements of the list is
returned.
(list-truth->maybe (maybe->list-truth x))
is an identity mapping.
[SRFI-189]{srfi.189
}
Like either->list
, it returns #f
if either is a Left.
If either is a Right, however, it returns a list of its payload values.
[SRFI-189]{srfi.189
}
The list-or-false argument must be #f
of a list.
If it is #f
, a Left with fail-objs …
is returned. If it is a list, a Right with elements of the list is
returned.
[SRFI-189]{srfi.189
}
If maybe is a Nothing, an EOF object is returned.
Otherwise, it must be a Just with one value, and its value is returned.
If maybe is a Just and it doesn’t have exactly one value, an error
is thrown.
[SRFI-189]{srfi.189
}
If obj is an EOF value, a Nothing is returned.
Otherwise, a Just wrapping obj is returned.
[SRFI-189]{srfi.189
}
If either is a Left, an EOF object is returned.
Otherwise, it must be a Right with one value, and its value is returned.
If either is a Right and it doesn’t have exactly one value, an error
is thrown.
[SRFI-189]{srfi.189
}
If obj is an EOF value, a Left with fail-objs … is returned.
Otherwise, a Right wrapping obj is returned.
[SRFI-189]{srfi.189
}
If maybe is a Just, returns its payload as multiple values.
If it is a Nothing, returns no values.
(Note that a Just with zero values also returns no values.)
[SRFI-189]{srfi.189
}
It first invokes a procedure producer with no values.
If it returns zero values, a Nothing is returned; otherwise,
a Just with those values are returned.
[SRFI-189]{srfi.189
}
If either is a Right, returns its payload as multiple values.
If it is a Left, returns no values.
(Note that a Right with zero values also returns no values.)
[SRFI-189]{srfi.189
}
It first invokes a procedure producer with no values.
If it returns zero values, a Left with fail-obj … as
its payload is returned.
If it returns one or more values,
a Right with those values are returned.
[SRFI-189]{srfi.189
}
If maybe is a Just with exactly one value, the value and #t
is returned. If maybe is a Nothing, two #f
is returned.
An error is thrown if maybe has a Just with zero or more than two
values.
[SRFI-189]{srfi.189
}
The inverse of maybe->two-values
. A procedure producer
is called with no arguments. It must return two values, a possible
payload value, and a boolean. If the second value is true,
a Just with the first value is returned. If the second value is #f
,
a Nothing is returned (the first return value is ignored).
[SRFI-189]{srfi.189
}
A procedure thunk is called without argument, wrapped by an
exception handler. If thunk raises a condition, it is
examined by pred. If pred returns true on the condition,
the exception is wrapped by a Left and returned.
If pred returns #f
, the exception is reraised.
If no exception is raised, the result(s) of thunk is wrapped
by a Right and returned.
[SRFI-189]{srfi.189
}
If the mtest expression yields a Just, evaluates then.
If the mtest expression yeilds a Nothing, evaluates else.
If the mtest expression doesn’t produce a Maybe, an error
is thrown.
[SRFI-189]{srfi.189
}
Evaluates maybe/either from left to right, as far as
each yields a Just/Right. If every expression yields a Just/Right,
the last one is returned. If it encounters an expression that
yields a Nothing/Left, it stops evaluating the rest of expressions and
returns the Nothing/Left.
If expressions yield something other than Maybe/Either, an error is thrown.
[SRFI-189]{srfi.189
}
Evaluates maybe/either from left to right, as far as
each yields a Nothing/Left. If it encounters an expression that
yields a Just/Right, it stops evaluating the rest of expressions and
returns it.
If expressions yield something other than Maybe/Either, an error is thrown.
[SRFI-189]{srfi.189
}
This is a Maybe/Either version of and-let*
.
Each claw can be either one of the following forms:
identifier
The identifier’s value is taken. It must be a Maybe/an Either, or an error is signaled. If it is a Just/Right, evaluation proceeds to the next claw. If it is a Nothing/Left, evaluation stops and the value is returned immediately.
(identifier expression)
The expression is evaluated. It must yield a Maybe/an Either, or an error is signaled. If it is a Just/Right, identifier is bound to its payload, and the rest of claws and body are processed with the scope of identifier. If it is a Nothing/Left, evaluation stops and the value is returned immediately. An error is signaled if a Just/Right doesn’t carry exactly one value.
( expression )
The expression is evaluated. It must yield a Maybe/an Either, or an error is signaled. If it is a Just/Right, evaluation proceeds to the next claw. If it is a Nothing/Left, evaluation stops and the value is returned immediately.
After all claws are processed and none yields a Nothing/Left, body … are evaluated.
[SRFI-189]{srfi.189
}
Multi-value payload version of maybe-let*
/either-let*
.
Each claw can be either one of the following forms:
identifier
The identifier’s value is taken. It must be a Maybe/an Either, or an error is signaled. If it is a Just/Right, evaluation proceeds to the next claw. If it is a Nothing/Left, evaluation stops and the value is returned immediately.
(formals expression)
The formals is the same as the formals of the lambda form, that is, a proper or dotted list of identifiers.
The expression is evaluated. It must yield a Maybe/an Either, or an error is signaled. If it is a Just/Right, identifiers in the formals are bound with the payload of the Just/Right, and the rest of claws and body are processed with the scope of those identifiers. If it is a Nothing/Left, evaluation stops and the value is returned immediately. An error is signaled if the formals doesn’t match the payload of the Just/Right.
( expression )
The expression is evaluated. It must yield a Maybe/an Either, or an error is signaled. If it is a Just/Right, evaluation proceeds to the next claw. If it is a Nothing/Left, evaluation stops and the value is returned immediately.
After all claws are processed and none yields a Nothing/Left, body … are evaluated.
[SRFI-189]{srfi.189
}
The body … is evaluated, and the value(s) it produces
are wrapped in a Right and returned. If an exception occurs in
body …, the thrown condition is passed to a predicate pred.
If the condition satisfies the predicate, it is wrapped in a Left
and returned. Otherwise, the condition is reraised with
raise-continuable.
This section describes procedures that deal with trivalent logic—a value can
be a false value (Just #f
), a true value
(Just
with anything other than #f
), and Nothing
.
If any of the arguments is Nothing
, the result becomes Nothing
(except tri=?
).
All the argument must be Maybe type, or an error is signalled.
[SRFI-189]{srfi.189
}
Returns Just #t
if maybe is trivalent-false,
Just #f
if maybe is triavlent-true, and
Nothing
if maybe is Nothing
.
[SRFI-189]{srfi.189
}
Returns Just #t
if arguments are either all trivalent-true
or all trivalent-false. Otherwise return Just #f
.
Note that if any of the argument is Nothing
, the result is
Just #f
(even all arguments are Nothing
).
[SRFI-189]{srfi.189
}
Returns Just #t
if all arguments are trivalent-true,
Just #f
if all arguments are Just
but at least one
of them is Just #f
, and Nothing
if any of the arguments
is Nothing
. If there’s no arguments, Just #t
is returned.
This is not a shortcut operation like and
.
[SRFI-189]{srfi.189
}
Returns Just #f
if all arguments are trivalent-false,
Just #t
if all arguments are Just
but at least one
of them is trivalent-true, and Nothing
if any of the arguments
is Nothing
. If there’s no arguments, Just #f
is returned.
This is not a shortcut operation like or
.
[SRFI-189]{srfi.189
}
If all arguments are Nothing
, Nothing
is returned.
Otherwise, first Just
is returned.