On this page:
3.11.1 The Option Datatype
3.11.2 Option Methods

3.11 option

include option
import option as ...

3.11.1 The Option Datatype

data Option<a>:
| none
| some(value :: a)

none :: Option<a>

some :: (value :: a) -> Option<a>

is-none :: (val :: Any) -> Boolean

is-some :: (val :: Any) -> Boolean

Option implements a functional programming idiom that is often used when a function may or may not return a valid or meaningful value. If there is no return value, then none is returned. If there is a meaningful return value, the value is wrapped in the some variant.

Some Pyret library functions return Option values, such as string-to-number. In this case, if the string is not a valid numeric value, none is returned; otherwise, the numeric value is wrapped in some. A cases expression can be used to evaluate both Option response variants.


fun set-angle(s :: String) -> Number: doc: "If s is not a numeric string, default to 0." cases(Option) string-to-number(s): | some(a) => a | none => 0 end where: set-angle("90") is 90 set-angle("") is 0 set-angle("x") is 0 end

In an contrasting example, the string-index-of function does not provide an Option return value, but instead returns a Number which is either a valid index Number or -1 if the string is not found.


fun find-smiley(s :: String) -> String: i = string-index-of(s, "😊") ask: | i == -1 then: "No smiley!" | otherwise: string-append("Smiley at ", num-to-string(i)) end where: find-smiley("abcd") is "No smiley!" find-smiley("a😊cd") is "Smiley at 1" end

If you wanted to create a version of find-smiley that returned an Option value, it might look like this:


fun option-smiley(s :: String) -> Option: i = string-index-of(s, "😊") ask: | i == -1 then: none | otherwise: some(i) end where: option-smiley("abcd") is none option-smiley("a😊cd") is some(1) end

3.11.2 Option Methods

.and-then :: (f :: (a -> b)) -> Option<b>

For none, returns none. For some, applies f to the value field and returns a new some with the updated value.


check: add1 = lam(n): n + 1 end n = none n.and-then(add1) is none s = some(5) s.and-then(add1) is some(6) end

.or-else :: (v :: a) -> a

For none, returns v. For some, returns the value field. Useful for providing default values.


check: n = none n.or-else(42) is 42 s = some(5) s.or-else(10) is 5 end

Our example above of set-angle, which defaults to 0, could be replaced with:


check: string-to-number("90").or-else(0) is 90 string-to-number("x").or-else(0) is 0 end