Option
Type Option represents an optional value: every Option is either Option:Some and contains a value, or Option:None, and does not. Common uses of an Option may involve:
- Initial values
- Return values for functions that are not defined over their entire input range (partial functions)
- Return value for otherwise reporting simple errors, where None is returned on error
- Optional object fields
- Values that can be loaned or “taken”
- Optional function arguments
function divide(numerator: number, denominator: number): Option<number>
if denominator == 0 then
None()
else
return Some(numerator / denominator)
end
end
Functions
okOr
Transforms the Option<T>
into a Result<T, E>
, mapping Option:Some(v)
to Result:Ok(v)
and Option:None to Result:Err(err)
.
Arguments passed to Option:okOr are eagerly evaluated; if you are passing the result of a function call, it is recommended to use Option:okOrElse, which is lazily evaluated.
local x: Option<string> = Some("foo")
assert(x:okOr(0) == Ok("foo"))
x = None()
assert(x:okOr(0) == Err(0))
okOrElse
Transforms the Option<T>
into a Result<T, E>
, mapping Option:Some(v)
to
Result:Ok(v)
and Option:None to Result:Err(err())
.
local x: Option<string> = Some("foo")
assert(x:okOrElse(function() return 0 end) == Ok("foo"))
x = None()
assert(x:okOrElse(function() return 0 end) == Err(0))
transpose
Transposes a Option of an Result into an Result of a Option.
Option:None will be mapped to Result:Ok(Option:None).
Option:Some(Result:Ok(_)
) and Option:Some(Result:Err(_
)) will
be mapped to Result:Ok(Option:Some(_)
) and Result:Err(_)
.
type SomeErr = {}
local x: Result<Option<number>, SomeErr> = Ok(Some(5))
local y: Option<Result<number, SomeErr>> = Some(Ok(5))
assert(x == y:transpose())
None
No value.
Some
Some value of type T
.
new
Converts a potentially nil
value into an Option.
isSome
Returns true
is the Option is an Option:Some value.
isSomeAnd
Returns true
is the Option is an Option:Some value and the value inside of it
matches a predicate.
isNone
Returns true
is the Option is an Option:None value.
expect
Returns the Option:Some.
local x: Option<string> = Some("value")
assert(x:expect("fruits are healthy") == "value")
local x: Option<string> = None()
x:expect("fruits are healthy") -- panics with `fruits are healthy`
Errors
Type | Description |
---|---|
panic | Panics if there is an [Option:None] with a custom panic message provided by `msg`. |
unwrap
Returns the Option:Some.
Because this function may panic, its use is generally discouraged. Instead, prefer to use Option:unwrapOr, Option:unwrapOrElse, or Option:unwrapOrDefault.
Errors
Type | Description |
---|---|
panic | Panics if the self value is [Option:None]. |
unwrapOr
Returns the contained Option:Some value or a provided default.
Arguments passed to unwrap_or are eagerly evaluated; if you are passing the result of a function call, it is recommended to use Option:unwrapOrElse, which is lazily evaluated.
assert(Some("car"):unwrapOr("bike") == "car")
assert(None():unwrapOr("bike") == "bike")
unwrapOrElse
Option.
unwrapOrElse
(
default:
(
)
→
T
--
The function which computes the default value
) →
T
Returns the contained Option:Some value or computes it from a function.
local k = 10
assert(Some(4).unwrapOrElse(function()
return 2 * k
end) == 4)
assert(None().unwrapOrElse(function()
return 2 * k
end) == 20)
map
Maps an Option to Option by applying a function to a contained value (if Option:Some) or returns Option:None(if Option:None).
local maybeSomeString: Option<string> = Some("Hello, World!")
local maybeSomeLen: Option<number> = maybeSomeString:map(function(s)
return #s
end)
assert(maybeSomeLen == 13)
local x: Option<string> = None()
assert(x:map(function(s)
return #s
end) == None())
inspect
Calls the provided closure with the contained value (if Option:Some).
local v = { 1, 2, 3, 4, 5 }
-- prints "got: 4"
local x: Option<number> = Option.new(v[4]):inspect(function(x)
print("got: " .. x)
end)
-- prints nothing
local x: Option<number> = Option.new(v[5]):inspect(function(x)
print("got: " .. x)
end)
mapOr
Returns the provided default result (if none), or applies a function to the contained value (if any).
Arguments passed to Option:mapOr are eagerly evaluated; if you are passing the result of a function call, it is recommended to use Option:mapOrElse, which is lazily evaluated.
local x: Option<string> = Some("foo")
assert(x.mapOr(42, function(v) return #v end) == 3)
local x: Option<string> = None()
assert(x.mapOr(42, function(v) return #v end) == 42)
mapOrElse
Option.
mapOrElse
(
default:
(
)
→
U
,
--
The function to compute the default value
op:
(
val:
T
)
→
U
--
The function to apply
) →
Option
<
T
>
Computes a default function result (if none), or applies a different function to the contained value (if any).
local k = 21;
local x: Option<string> = Some("foo")
assert(
x:mapOrElse(
function() return 2 * k end,
function(v) return #v end
) == 3
)
local x: Option<string> = None()
assert(
x:mapOrElse(
function() return 2 * k end,
function(v) return #v end
) == 42
)
and_
Returns Option:None if the option is Option:None, otherwise returns optb
.
Arguments passed to and are eagerly evaluated; if you are passing the result of a function call, it is recommended to use Option:andThen, which is lazily evaluated.
local x: Option<number> = Some(2)
local y: Option<String> = None()
assert(x:and_(y) == None())
local x: Option<number> = None()
local y: Option<string> = Some("foo")
assert(x:and_(y) == None())
local x: Option<number> = Some(2)
local y: Option<string> = Some("foo")
assert(x:and_(y) == Some("foo"))
local x: Option<u32> = None()
local y: Option<string> = None()
assert(x:and_(y), None())
andThen
Returns Option:None if the option is Option:None, otherwise calls op
with the wrapped
value and returns the result.
Some languages call this operation flatmap.
function sqThenToString(x: number): Option<string>
return Option.new(x ^ 2):map(function(sq)
return tostring(sq)
end)
end
assert(Some(2):andThen(sqThenToString) == Some(tostring(4)))
assert(None():andThen(sqThenToString) == None())
Often used to chain fallible operations that may return Option:None.
local arr2d = { { "A0", "A1" }, { "B0", "B1" } }
local item01: Option<string> = Option.new(arr2d[1]):andThen(function(row)
return row[2]
end)
assert(item01 == Some("A1"))
local item20: Option<string> = Option.new(arr2d[3]):andThen(function(row)
return row[0]
end)
assert(item20 == None())
filter
Option.
filter
(
predicate:
(
val:
T
)
→
boolean
--
The predicate function which must match an element
) →
Option
<
T
>
Returns Option:None if the option is Option:None, otherwise calls predicate
with
the wrapped value and returns:
- Option:Some if predicate returns
true
(wheret
is the wrapped value), and - Option:None if predicate returns
false
.
function isEven(n: number): boolean
return n % 2 == 0
end
assert(None():filter(isEven) == None())
assert(Some(3):filter(isEven) == None())
assert(Some(4):filter(isEven) == Some(4))
or_
Returns the option if it contains a value, otherwise returns optb
.
Arguments passed to Option:or_ are eagerly evaluated; if you are passing the result of a function call, it is recommended to use Option:orElse, which is lazily evaluated.
local x: Option<number> = Some(2)
local y: Option<number> = None()
assert(x:or_(y) == Some(2))
local x: Option<number> = None()
local y: Option<number> = Some(100)
assert(x:or_(y) == Some(100))
local x: Option<number> = Some(2)
local y: Option<number> = Some(100)
assert(x:or_(y) == Some(2))
local x: Option<number> = None()
local y: Option<number> = None()
assert(x:or_(y), None())
orElse
Returns the option if it contains a value, otherwise calls op
and returns the result.
function nobody(): Option<string>
return None()
end
function vikings(): Option<string>
return Some("vikings")
end
assert(Some("barbarians"):orElse(vikings) == Some("barbarians"))
assert(None():orElse(vikings) == Some("vikings"))
assert(None():orElse(nobody) == None())
xor
Returns Option:Some if exactly one of self
, optb
is Option:Some,
otherwise returns Option:None.
local x: Option<number> = Some(2)
local y: Option<number> = None()
assert(x:xor(y) == Some(2))
local x: Option<number> = None()
local y: Option<number> = Some(2)
assert(x:xor(y) == Some(2))
local x: Option<number> = Some(2)
local y: Option<number> = Some(2)
assert(x:xor(y) == None())
local x: Option<number> = None()
local y: Option<number> = None()
assert(x:xor(y) == None())
insert
Inserts value into the option, then returns it.
If the option already contains a value, the old value is dropped.
See also Option:getOrInsert, which doesn’t update the value if the option already contains Option:Some.
local opt: Option<number> = None()
local val: number = opt:insert(1)
assert(val == 1)
assert(opt:unwrap() == 1)
local val: number = opt:insert(2)
assert(val == 2)
getOrInsert
Inserts value into the option, then returns it.
If the option already contains a value, the old value is dropped.
See also Option:getOrInsert, which doesn’t update the value if the option already contains Option:Some.
local opt: Option<number> = None()
local val: number = opt:insert(1)
assert(val == 1)
assert(opt:unwrap() == 1)
local val: number = opt:insert(2)
assert(val == 2)
take
Takes the value out of the option, leaving an Option:None in its place.
local x: Option<number> = Some(2)
local y: Option<number> = x.take()
assert(x == None())
assert(y == Some(2))
local x: Option<number> = None()
local y: Option<number> = x.take()
assert(x == None())
assert(y == None())
replace
Replaces the actual value in the option by the value given in parameter, returning the old value if present, leaving an Option:Some in its place without deinitializing either one.
local x: Option<number> = Some(2)
local old: Option<number> = x:replace(5)
assert(x == Some(5))
assert(old == Some(2))
local x: Option<number> = None()
local old: Option<number> = x:replace(3)
assert(x == Some(3))
assert(old == None())
contains
Returns true if val
is contained in the Option:Some.
local x: Option<number> = Some(2)
local y: Option<number> = None()
assert(x:contains(2))
assert(x:contains(4))
assert(not y:contains(2))
zip
Zips self
with another Option.
If self
is Option:Some and other is Option:Some, this method returns
Option:Some({s, o}). Otherwise, Option:None is returned.
local x: Option<number> = Some(1)
local y: Option<string> = Some("hi")
local z: Option<number> = None()
assert(x:zip(y) == Some({ 1, "hi" }))
assert(x:zip(z) == None())
zipWith
Zips self
and another Option with function op
.
If self
is Option:Some and other is Option:Some, this method returns
Option:Some(op(s, o)). Otherwise, Option:None is returned.
type Point = {
x: number,
y: number,
}
local Point: Point & {
new: (x: number, y: number) -> Point,
} = {}
function Point.new(x: number, y: number): Point
return {
x = x,
y = y,
}
end
local xCoord: Option<number> = Some(17.5)
local yCoord: Option<number> = Some(42.7)
assert(xCoord:zipWith(yCoord, Point.new), Some({ x = 17.5, y = 42.7 }))
assert(x:zipWith(None(), Point.new), None())
unzip
Unzips an option containing a table of two options.
If self
is Some({a, b})
this method returns (Some(a), Some(b))
.
Otherwise, (None(), None())
is returned.
local x: Option<{ number | string }> = Some({ 1, "hi" })
local y: Option<{ number }> = None()
assert((x:unzip() == Some(1), Some("hi")))
assert((y:unzip() == None(), None()))
unwrapUnchecked
Returns the inner value wrapped by the Option.
local x: Option<string> = Some("lol")
local y: Option<string> = None()
assert(x:unwrapUnchecked() == "lol")
assert(y:unwrapUnchecked() == nil)
display
Returns a formatted representation of the option, often used for printing to stdout.
local x: Option<number> = Some(123)
local y: Option<number> = None()
print(x:display()) -- prints `Option::Some(123)`
print(y:display()) -- prints `Option::None`