Result
UpdatedResult<T, E>
local r: Result<number, string> = Ok(1) local v = r:unwrap_or(0) match r with case Ok(n) then print(n) case Err(e) then warn(e) end
Ok(value) or Err(error), from the std. A function that can fail returns one, and the caller reads it with a match, an if local Ok(v) = r, or the methods. try expr inside a function that returns a Result returns the Err early, and at the module top level it returns the Err from the chunk; try do ... end turns a throw into an Err; try await does the same for a Future.
An Err carries trace, a traceback Result.pcall and try fill in and Err(e, trace) sets by hand. map and map_err yield a Result of the same surface whose own map is any: Luau rejects an alias that names itself with other arguments. and_then(f) runs f on an Ok value and returns the Result f builds, or_else(f) does the same for an Err, and unwrap_or_else(f) calls f with the error only when there is one, so a costly fallback runs only when it is needed. Result<T, E> is covariant, so a Result<Boost, E> passes where Result<any, E> is asked.
Statics
Result.pcall
Result.pcall<T>(f: (...any) -> T, ...: any): Result<T, string>
Calls f with the arguments after it: Ok of what it returns, or Err of what it threw. The value type follows f, and the Err carries the traceback in trace. A function that returns nothing gives Result<nil, string>.
local r = Result.pcall(string.rep, "a", 3) print(r:unwrap_or(""))
Methods
Result:unwrap
Result:unwrap(): T
The value of an Ok. An Err raises, with the error and its trace in the message. Reach for it when an Err is a bug, not a case.
local r: Result<number, string> = Ok(1) print(r:unwrap())
Result:expect
Result:expect(message: string): T
The value of an Ok. An Err raises with message, which says what the caller expected.
local r: Result<number, string> = Ok(1) print(r:expect("the config sets a width"))
Result:unwrap_or
Result:unwrap_or<D>(default: D): T | D
The value of an Ok, or default. The result type is T | D, so r:unwrap_or(nil) is T?.
local r: Result<number, string> = Err("no") print(r:unwrap_or(0))
Result:map
Result:map<U>(f: (T) -> U): Result<U, E>
Ok(f(value)), or the same Err untouched. The mapped Result names a second alias, so a third map in one chain types as any.
local r: Result<number, string> = Ok(2) print(r:map(function(n) return n * 2 end):unwrap())
Result:map_err
Result:map_err<F>(f: (E) -> F): Result<T, F>
Err(f(error)), or the same Ok untouched. Use it to turn a low level error into one the caller names.
local r: Result<number, string> = Err("io") print(r:map_err(function(e) return `read: {e}` end):is_err())
Result:is_ok
Result:is_ok(): boolean
Whether the Result is an Ok. It narrows nothing; a match or if local Ok(v) = r binds the value.
local r: Result<number, string> = Ok(1) print(r:is_ok())
Result:is_err
Result:is_err(): boolean
Whether the Result is an Err.
local r: Result<number, string> = Err("no") print(r:is_err())
Result:ok
Result:ok(): T?
The value of an Ok, or nil for an Err. It drops the error, which is what ?? wants on the other side.
local r: Result<number, string> = Ok(1) print(r:ok() ?? 0)
Fields
Result.tag
Result.tag: "Ok" | "Err"
Which case the Result is, as a string. A match reads it for you; the field is there for code that stores or sends the tag.
local r: Result<number, string> = Ok(1) print(r.tag)
Result.trace
Result.trace: string?
The traceback of an Err. try and Result.pcall fill it in, Err(e, trace) sets it by hand, and unwrap prints it under the error.
local r = Result.pcall(error, "boom") print(r.trace ?? "no trace")
