essenceDocumentation
essenceDocs
on this pageAt a glance
Coming from JavaScript?

Optional

choice

A value that is there or is not, and the methods that test, read, transform and fall back from it.

is

A value that is there or is not: #Value holds an item, and #Empty holds nothing.

Every Method that can come back empty answers one of these. The Choice nests, so #Value(#Empty) is not #Empty.

Taught on: Optional.

Declaration
choice Optional<ItemType> {
	Value { item: ItemType },
	Empty,
}

At a glance

Declared
namespace Optional<infer ItemType> for Optional<ItemType>
Conforms to
Views
  • NestedOptional for Optional<Optional<ItemType>> in Nested

A view is a namespace for a narrower type. A value of that type has the view's methods on top of its own.

Equality and printing

is

on Optional<ItemType>

Answers whether the Optional is the given one, or whether it holds the given bare value.

Two Optionals are equal when they are the same Case and hold equal values. An empty Optional is never equal to a bare value. An Optional holding an Optional reaches the first entry, so #Value(#Empty)::is(#Empty) asks about the receiver and answers false. The Method is available whenever the payload conforms to Equatable.

Example
constant found: Optional<Integer> = #Value(3)
constant missing: Optional<Integer> = #Empty

expect found::is(#Value(3))
expect found::is(3)
expect missing::is(3)::negate()
is<ItemType is Equatable>(_ other: Optional<ItemType>) -> Boolean
NameTypeDescription
_Optional<ItemType>the Optional to compare against

true when both are empty, or both hold equal values.

is<ItemType is Equatable>(_ other: ItemType) -> Boolean
NameTypeDescription
_ItemTypethe bare value to compare against

true when the Optional holds a value equal to it; false when it is empty.

isNot

on Optional<ItemType>

Answers whether the Optional differs from the given one, or whether it does not hold the given bare value.

An empty Optional holds no bare value, so it always differs from one. The Method is available whenever the payload conforms to Equatable.

Example
constant found: Optional<Integer> = #Value(3)
constant missing: Optional<Integer> = #Empty

expect found::isNot(#Empty)
expect found::isNot(4)
expect missing::isNot(3)
isNot<ItemType is Equatable>(_ other: Optional<ItemType>) -> Boolean
NameTypeDescription
_Optional<ItemType>the Optional to compare against

true when the two differ in Case or in value.

isNot<ItemType is Equatable>(_ other: ItemType) -> Boolean
NameTypeDescription
_ItemTypethe bare value to compare against

true when the Optional is empty or holds a different value.

toString

on Optional<ItemType>

toString<ItemType is Printable>() -> String

Answers the Optional as a String, written Value(…) or Empty.

The payload renders through its own toString, and a String payload is quoted: #Value("a") answers Value("a"). A String prints bare on its own and quoted inside a structure. The Method is available whenever the payload conforms to Printable.

the text Value(…) around the payload, or Empty.

Example
constant found: Optional<String> = #Value("Ada")
constant missing: Optional<String> = #Empty

expect found::toString()::is("Value(\"Ada\")")
expect missing::toString()::is("Empty")

Testing

hasValue

on Optional<ItemType>

Answers whether the Optional holds a value, or holds a value the check accepts.

true when there is a value, or when the check accepts the value.

hasValue() -> Boolean

Answers whether the Optional holds a value.

true when there is a value.

Example
constant found: Optional<Integer> = #Value(3)
constant missing: Optional<Integer> = #Empty

expect found::hasValue()
expect missing::hasValue()::negate()
hasValue(where check: (_: ItemType) -> Boolean) -> Boolean

Answers whether the Optional holds a value the check accepts.

An empty Optional answers false, and the check does not run.

NameTypeDescription
where(_: ItemType) -> Booleanthe question asked of the value

true when there is a value and the check accepts it.

Example
constant found: Optional<Integer> = #Value(3)
constant missing: Optional<Integer> = #Empty

expect found::hasValue(where (count) { <- count::isOdd() })
expect missing::hasValue(where (count) { <- count::isOdd() })::negate()

isEmpty

on Optional<ItemType>

isEmpty() -> Boolean

Answers whether the Optional holds no value, the opposite of hasValue.

true when there is no value.

Example
constant found: Optional<Integer> = #Value(3)
constant missing: Optional<Integer> = #Empty

expect missing::isEmpty()
expect found::isEmpty()::negate()

Reading

value

on Optional<ItemType>

value(defaultingTo fallback: ItemType) -> ItemType

Answers the value, or the given fallback when there is none.

The call collapses an Optional back to a bare value: list::firstItem()::value(defaultingTo 0).

NameTypeDescription
defaultingToItemTypethe value to answer with when there is none

the value, or the fallback in its place.

Example
constant found: Optional<Integer> = #Value(3)
constant missing: Optional<Integer> = #Empty

expect found::value(defaultingTo 0)::is(3)
expect missing::value(defaultingTo 0)::is(0)

Transforming

map

on Optional<ItemType>

map<infer Other>(
	_ transform: (_: ItemType) -> Other,
) -> Optional<Other>

Answers the value transformed, wrapped in an Optional.

An empty Optional answers empty, and the transform does not run. This is List::map for the at-most-one case.

NameTypeDescription
_(_: ItemType) -> Otherthe transform to run on the value

the transformed value in an Optional, or an empty Optional.

Example
constant found: Optional<Integer> = #Value(3)
constant missing: Optional<Integer> = #Empty

expect found::map((count) { <- count::add(1) })::is(4)
expect missing::map((count) { <- count::add(1) })::isEmpty()

andThen

on Optional<ItemType>

andThen<infer Other>(
	_ step: (_: ItemType) -> Optional<Other>,
) -> Optional<Other>

Answers with the Optional the step answers for the value.

The two Optionals do not nest: the answer has one level. An empty Optional answers empty, and the step does not run.

NameTypeDescription
_(_: ItemType) -> Optional<Other>the step to run on the value

the Optional the step answers, or an empty Optional.

Example
constant typed: Optional<String> = #Value("42")
constant missing: Optional<String> = #Empty

expect typed::andThen((text) { <- Integer.parse(text) })::is(42)
expect missing::andThen((text) { <- Integer.parse(text) })::isEmpty()

keep

on Optional<ItemType>

keep(where check: (_: ItemType) -> Boolean) -> Optional<ItemType>

Answers the Optional when its value passes the check, and empty otherwise.

An empty Optional answers empty, and the check does not run. This is List::everyItem(where:) for the at-most-one case.

NameTypeDescription
where(_: ItemType) -> Booleanthe question asked of the value

the Optional unchanged when the value passes, an empty Optional otherwise.

Example
constant found: Optional<Integer> = #Value(3)

expect found::keep(where (count) { <- count::isOdd() })::is(3)
expect found::keep(where (count) { <- count::isEven() })::isEmpty()

Falling back

or

on Optional<ItemType>

or(_ other: Optional<ItemType>) -> Optional<ItemType>

Answers the Optional when it holds a value, and the given Optional otherwise.

A chain of calls reads as a list of fallbacks, and the first value in it decides the answer. Two empty Optionals answer empty. The Argument is read whether or not the receiver holds a value.

NameTypeDescription
_Optional<ItemType>the Optional to fall back on

the receiver when it holds a value, and the Argument in its place otherwise.

Example
constant missing: Optional<Integer> = #Empty

expect missing::or(#Value(2))::is(2)

Combining and converting

pair

on Optional<ItemType>

pair<infer Other>(
	with other: Optional<Other>,
) -> Optional<{ first: ItemType, second: Other }>

Answers the two values in one Record, and empty when either Optional is empty.

This is List::pair(with:) for the at-most-one case. Both values are needed, so one empty Optional answers empty.

NameTypeDescription
withOptional<Other>the Optional to pair the value with

a Record holding this value under first and the other under second, or an empty Optional.

Example
constant age: Optional<Integer> = #Value(36)
constant name: Optional<String> = #Value("Ada")
constant missing: Optional<String> = #Empty

expect age::pair(with name)::is({ first = 36, second = "Ada" })
expect age::pair(with missing)::isEmpty()

toList

on Optional<ItemType>

toList() -> List<ItemType>

Answers a List holding the value, and the empty List when there is none.

The answer holds one item at most. It is the bridge to the Methods a List answers, and OptionalList::values() is the bridge back.

the List of the value, or the empty List.

Example
constant found: Optional<Integer> = #Value(3)
constant missing: Optional<Integer> = #Empty

expect found::toList()::is([3])
expect missing::toList()::isEmpty()

toResult

on Optional<ItemType>

toResult<infer FailureType>(
	failingWith reason: FailureType,
) -> Result<ItemType, FailureType>

Answers the value as a Result, failing with the given reason where there is none.

An Optional says that there is no value, and a Result says why. The reason is read whether or not it is used.

The reason's own Type decides the Result's failure Type. A bare #NotFound binds it to that Case alone, and a Problem#NotFound written out does the same. The next call in the chain then works on a Result of a Type it does not expect. Bind the reason to a Constant annotated with the Choice to say the Choice.

NameTypeDescription
failingWithFailureTypethe reason to fail with where there is no value

the value in a Result, or the reason as a failure.

Example
constant missing: Optional<Integer> = #Empty

expect missing::toResult(failingWith "gone")::is(#Failure("gone"))

Nested

flatten

on Optional<Optional<ItemType>>

flatten() -> Optional<ItemType>

Answers the inner Optional, one level down.

An empty outer Optional answers empty.

the flattened Optional.

Example
constant nested: Optional<Optional<Integer>> = #Value(#Value(3))
constant missing: Optional<Optional<Integer>> = #Empty

expect nested::flatten()::is(3)
expect missing::flatten()::isEmpty()

See also

esc