`srfi.189`

- Maybe and Either: optional container types ¶- Module:
**srfi.189**¶ -
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.

- Class:
**<maybe>**¶ - Class:
**<just>**¶ - Class:
**<nothing>**¶ {

`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`

.

- Class:
**<either>**¶ - Class:
**<right>**¶ - Class:
**<left>**¶ {

`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`

.

- Function:
**maybe?**`obj`¶ - Function:
**just?**`obj`¶ - Function:
**nothing?**`obj`¶ [SRFI-189]{

`srfi.189`

} Type predicates. Returns`#t`

iff`obj`is a Maybe, a Just, or a Nothing, respectively.

- Function:
**either?**`obj`¶ - Function:
**right?**`obj`¶ - Function:
**left?**`obj`¶ [SRFI-189]{

`srfi.189`

} Type predicates. Returns`#t`

iff`obj`is a Either, a Right, or a Left, respectively.

- Function:
**maybe=**`elt= maybe1 maybe …`¶ [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=`.

- Function:
**either=**`elt= either1 either …`¶ [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=`.

- Function:
**just**`obj …`¶ [SRFI-189]{

`srfi.189`

} Returns a Just with`obj`… as its payload.

- Function:
**nothing**¶ [SRFI-189]{

`srfi.189`

} Returns a Nothing.

- Function:
**right**`obj …`¶ - Function:
**left**`obj …`¶ [SRFI-189]{

`srfi.189`

} Returns a Right or a Left respectively, with`obj`… as its payload.

- Function:
**list->just**`objs`¶ - Function:
**list->right**`objs`¶ - Function:
**list->left**`objs`¶ [SRFI-189]{

`srfi.189`

} Returns a Just, Right or Left respectively, with`objs`as its payload.

- Function:
**maybe->either**`maybe obj …`¶ [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.

- Function:
**either->maybe**`either`¶ [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.

- Function:
**either-swap**`either`¶ [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.

- Function:
**maybe-ref**`maybe failure :optional success`¶ [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

- Function:
**either-ref**`either failure :optional success`¶ [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.

- Function:
**maybe-ref/default**`maybe default …`¶ [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.

- Function:
**either-ref/default**`maybe default …`¶ [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.

- Function:
**maybe-join**`maybe`¶ [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.

- Function:
**either-join**`either`¶ [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.

- Function:
**maybe-bind**`maybe mproc mproc2 …`¶ [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)

- Function:
**either-bind**`either mproc mproc2 …`¶ [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)

- Function:
**maybe-compose**`mproc mproc2 …`¶ - Function:
**either-compose**`mproc mproc2 …`¶ [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.)

- Function:
**maybe-length**`maybe`¶ - Function:
**either-length**`either`¶ [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.

- Function:
**maybe-filter**`pred maybe`¶ - Function:
**either-filter**`pred either obj …`¶ [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.

- Function:
**maybe-remove**`pred maybe`¶ - Function:
**either-remove**`pred either obj …`¶ [SRFI-189]{

`srfi.189`

} Like`maybe-filter`

/`either-filter`

, but the meaning of`pred`is reversed.

- Function:
**maybe-sequence**`mappable cmap :optional aggregator`¶ - Function:
**either-sequence**`mappable cmap :optional aggregator`¶ [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`

.

- Function:
**maybe-map**`proc maybe`¶ - Function:
**either-map**`proc either`¶ [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.

- Function:
**maybe-for-each**`proc maybe`¶ - Function:
**either-for-each**`proc either`¶ [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.

- Function:
**maybe-fold**`kons knil maybe`¶ - Function:
**either-fold**`kons knil either`¶ [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.

- Function:
**maybe-unfold**`p f g seed …`¶ - Function:
**either-unfold**`p f g seed …`¶ [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.

- Function:
**maybe->list**`maybe`¶ [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.

- Function:
**list->maybe**`lis`¶ [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.

- Function:
**either->list**`either`¶ [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.

- Function:
**list->either**`lis obj …`¶ [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.

- Function:
**maybe->truth**`maybe`¶ [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`

.

- Function:
**truth->maybe**`obj`¶ [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.

- Function:
**either->truth**`either`¶ [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`

.

- Function:
**truth->either**`obj fail-obj …`¶ [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.

- Function:
**maybe->list-truth**`maybe`¶ [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.

- Function:
**list-truth->maybe**`lis-or-false`¶ [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.

- Function:
**either->list-truth**`either`¶ [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.

- Function:
**list-truth->either**`lis-or-false fail-objs …`¶ [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.

- Function:
**maybe->generation**`maybe`¶ [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.

- Function:
**generation->maybe**`obj`¶ [SRFI-189]{

`srfi.189`

} If`obj`is an EOF value, a Nothing is returned. Otherwise, a Just wrapping`obj`is returned.

- Function:
**either->generation**`either`¶ [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.

- Function:
**generation->either**`obj fail-objs …`¶ [SRFI-189]{

`srfi.189`

} If`obj`is an EOF value, a Left with`fail-objs`… is returned. Otherwise, a Right wrapping`obj`is returned.

- Function:
**maybe->values**`maybe`¶ [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.)

- Function:
**values->maybe**`producer`¶ [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.

- Function:
**either->values**`either`¶ [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.)

- Function:
**values->either**`producer fail-obj …`¶ [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.

- Function:
**maybe->two-values**`maybe`¶ [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.

- Function:
**two-values->maybe**`producer`¶ [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).

- Function:
**exception->either**`pred thunk`¶ [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.

- Macro:
**maybe-if**`mtest then else`¶ [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.

- Macro:
**maybe-and**`maybe …`¶ - Macro:
**either-and**`either …`¶ [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.

- Macro:
**maybe-or**`maybe …`¶ - Macro:
**either-or**`either …`¶ [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.

- Macro:
**maybe-let***`( claw … ) body …`¶ - Macro:
**either-let***`( claw … ) body …`¶ [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`claw`s 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.

- Macro:
**maybe-let*-values**`( mv-claw … ) body …`¶ - Macro:
**either-let*-values**`( mv-claw … ) body …`¶ [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`claw`s 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.

- Macro:
**either-guard**`pred body …`¶ [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.

- Function:
**tri-not**`maybe`¶ [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`

.

- Function:
**try=?**`maybe …`¶ [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`

).

- Function:
**try-and**`maybe …`¶ [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`

.

- Function:
**try-or**`maybe …`¶ [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`

.

- Function:
**try-merge**`maybe …`¶ [SRFI-189]{

`srfi.189`

} If all arguments are`Nothing`

,`Nothing`

is returned. Otherwise, first`Just`

is returned.

DRAFT