diff --git a/lib/conversion.luau b/lib/conversion.luau index e77e38e..a55588b 100644 --- a/lib/conversion.luau +++ b/lib/conversion.luau @@ -19,6 +19,24 @@ export type Result = result.Result local Ok = result.Ok local Err = result.Err +--[=[ + @within Result + + Converts from [Result]`` to [Option]``. + + Converts `self` into an [Option]``, and discarding the error, if any. + + ```lua + local x: Result = Ok(2) + assert(x:ok() == Some(2)) + + x = Err("Nothing here") + assert(x:ok() == None()) + ``` + + @param self Result + @return Option +]=] function Result.ok(self: Result): Option if self:isOk() then if self._value == nil then @@ -31,6 +49,24 @@ function Result.ok(self: Result): Option return None() end +--[=[ + @within Result + + Converts from [Result]`` to [Option]``. + + Converts `self` into an [Option]``, and discarding the success value, if any. + + ```lua + local x: Result = Ok(2) + assert(x:ok() == Some(2)) + + x = Err("Nothing here") + assert(x:ok() == None()) + ``` + + @param self Result + @return Option +]=] function Result.err(self: Result): Option if self:isErr() then return Option.new(self._error) :: Option @@ -39,9 +75,27 @@ function Result.err(self: Result): Option return None() end +--[=[ + @within Result + + Transposes a [Result] of an [Option] into an [Option] of a [Result]. + + [Result:Ok]\([Option:None]\) will be mapped to [Option:None]. + [Result:Ok]\([Option:Some]`(_)`\) and [Result:Err]\(`_`\) will be mapped to + [Option:Some]\([Result:Ok]`(_)`\) and [Option:Some]\([Option:Err]`(_)`\). + + ```lua + type SomeErr = {} + + local x: Result, SomeErr> = Ok(Some(2)) + local y: Option> = Some(Ok(2)) + assert(x:transpose() == y) + ``` + + @param self Result, E> + @return Option> +]=] function Result.transpose(self: Result, E>): Option> - -- TODO: Instead of checking whether values are nil, use - -- utility methods for Options once available if self._value == None() then return None() elseif self:isOkAnd(function(val): boolean @@ -55,6 +109,27 @@ function Result.transpose(self: Result, E>): Option error("`Result` is not transposable") end +--[=[ + @within Option + + Transforms the [Option]`` into a [Result]``, 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. + + ```lua + local x: Option = Some("foo") + assert(x:okOr(0) == Ok("foo")) + + x = None() + assert(x:okOr(0) == Err(0)) + ``` + + @param self Option + @param err E + @return Result +]=] function Option.okOr(self: Option, err: E): Result if self:isSome() then return Ok(self._optValue) @@ -63,6 +138,24 @@ function Option.okOr(self: Option, err: E): Result return Err(err) end +--[=[ + @within Option + + Transforms the [Option]`` into a [Result]``, mapping [Option:Some]`(v)` to + [Result:Ok]`(v)` and [Option:None] to [Result:Err]`(err())`. + + ```lua + local x: Option = Some("foo") + assert(x:okOrElse(function() return 0 end) == Ok("foo")) + + x = None() + assert(x:okOrElse(function() return 0 end) == Err(0)) + ``` + + @param self Option + @param err () -> E + @return Result +]=] function Option.okOrElse(self: Option, err: () -> E): Result if self:isSome() then return Ok(self._optValue :: T) @@ -71,6 +164,26 @@ function Option.okOrElse(self: Option, err: () -> E): Result return Err(err()) end +--[=[ + @within Option + + 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]`(_)`. + + ```lua + type SomeErr = {} + + local x: Result, SomeErr> = Ok(Some(5)) + local y: Option> = Some(Ok(5)) + assert(x == y:transpose()) + ``` + + @param self Option> + @return Result, E> +]=] function Option.transpose(self: Option>): Result, E> if self:isSome() then local inner = self._optValue diff --git a/lib/option.luau b/lib/option.luau index fa4f422..4a20824 100644 --- a/lib/option.luau +++ b/lib/option.luau @@ -3,8 +3,9 @@ local tableEq = require("util").tableEq --[=[ @class Option - Type [Option] represents an optional value: every [Option] is either [Some] and contains a - value, or [None], and does not. Common uses of an [Option] may involve: + 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)