mirror of
https://github.com/CompeyDev/rusty-luau.git
synced 2024-12-12 04:40:40 +00:00
chore: apply formatting
This commit is contained in:
parent
6d39f55e01
commit
2df6d06c41
7 changed files with 488 additions and 435 deletions
|
@ -4,17 +4,17 @@ local Ok = result.Ok
|
||||||
local Err = result.Err
|
local Err = result.Err
|
||||||
|
|
||||||
local function canError(): Result<number, string>
|
local function canError(): Result<number, string>
|
||||||
if math.round(math.random()) == 1 then
|
if math.round(math.random()) == 1 then
|
||||||
return Err("you DIED")
|
return Err("you DIED")
|
||||||
end
|
end
|
||||||
|
|
||||||
return Ok(69)
|
return Ok(69)
|
||||||
end
|
end
|
||||||
|
|
||||||
function main()
|
function main()
|
||||||
local val = canError():unwrap()
|
local val = canError():unwrap()
|
||||||
|
|
||||||
print("got value: ", val)
|
print("got value: ", val)
|
||||||
end
|
end
|
||||||
|
|
||||||
return main()
|
return main()
|
||||||
|
|
|
@ -38,15 +38,15 @@ local Err = result.Err
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Result.ok<T, E>(self: Result<T, E>): Option<T>
|
function Result.ok<T, E>(self: Result<T, E>): Option<T>
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
if self._value == nil then
|
if self._value == nil then
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
return Some(self._value)
|
return Some(self._value)
|
||||||
end
|
end
|
||||||
|
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -68,11 +68,11 @@ end
|
||||||
@return Option<E>
|
@return Option<E>
|
||||||
]=]
|
]=]
|
||||||
function Result.err<T, E>(self: Result<T, E>): Option<E>
|
function Result.err<T, E>(self: Result<T, E>): Option<E>
|
||||||
if self:isErr() then
|
if self:isErr() then
|
||||||
return Option.new(self._error) :: Option<E>
|
return Option.new(self._error) :: Option<E>
|
||||||
end
|
end
|
||||||
|
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -96,17 +96,19 @@ end
|
||||||
@return Option<Result<T, E>>
|
@return Option<Result<T, E>>
|
||||||
]=]
|
]=]
|
||||||
function Result.transpose<T, E>(self: Result<Option<T>, E>): Option<Result<T, E>>
|
function Result.transpose<T, E>(self: Result<Option<T>, E>): Option<Result<T, E>>
|
||||||
if self._value == None() then
|
if self._value == None() then
|
||||||
return None()
|
return None()
|
||||||
elseif self:isOkAnd(function(val): boolean
|
elseif
|
||||||
return val._optValue == nil
|
self:isOkAnd(function(val): boolean
|
||||||
end) then
|
return val._optValue == nil
|
||||||
return Some(Ok(self._value._optValue))
|
end)
|
||||||
elseif self:isErr() then
|
then
|
||||||
return Some(Err(self._error))
|
return Some(Ok(self._value._optValue))
|
||||||
end
|
elseif self:isErr() then
|
||||||
|
return Some(Err(self._error))
|
||||||
|
end
|
||||||
|
|
||||||
error("`Result` is not transposable")
|
error("`Result` is not transposable")
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -131,11 +133,11 @@ end
|
||||||
@return Result<T, E>
|
@return Result<T, E>
|
||||||
]=]
|
]=]
|
||||||
function Option.okOr<T, E>(self: Option<T>, err: E): Result<T, E>
|
function Option.okOr<T, E>(self: Option<T>, err: E): Result<T, E>
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return Ok(self._optValue)
|
return Ok(self._optValue)
|
||||||
end
|
end
|
||||||
|
|
||||||
return Err(err)
|
return Err(err)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -157,11 +159,11 @@ end
|
||||||
@return Result<T, E>
|
@return Result<T, E>
|
||||||
]=]
|
]=]
|
||||||
function Option.okOrElse<T, E>(self: Option<T>, err: () -> E): Result<T, E>
|
function Option.okOrElse<T, E>(self: Option<T>, err: () -> E): Result<T, E>
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return Ok(self._optValue :: T)
|
return Ok(self._optValue :: T)
|
||||||
end
|
end
|
||||||
|
|
||||||
return Err(err())
|
return Err(err())
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -185,26 +187,29 @@ end
|
||||||
@return Result<Option<T>, E>
|
@return Result<Option<T>, E>
|
||||||
]=]
|
]=]
|
||||||
function Option.transpose<T, E>(self: Option<Result<T, E>>): Result<Option<T>, E>
|
function Option.transpose<T, E>(self: Option<Result<T, E>>): Result<Option<T>, E>
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
local inner = self._optValue
|
local inner = self._optValue
|
||||||
assert(self.typeId == "Option" and inner.typeId == "Result", "Only an `Option` of a `Result` can be transposed")
|
assert(
|
||||||
|
self.typeId == "Option" and inner.typeId == "Result",
|
||||||
|
"Only an `Option` of a `Result` can be transposed"
|
||||||
|
)
|
||||||
|
|
||||||
if inner:isOk() then
|
if inner:isOk() then
|
||||||
return Some(Ok(inner._value))
|
return Some(Ok(inner._value))
|
||||||
elseif inner:isErr() then
|
elseif inner:isErr() then
|
||||||
return Some(Err(inner._error))
|
return Some(Err(inner._error))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return Ok(None())
|
return Ok(None())
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Ok = Ok,
|
Ok = Ok,
|
||||||
Err = Err,
|
Err = Err,
|
||||||
Result = Result,
|
Result = Result,
|
||||||
|
|
||||||
Some = Some,
|
Some = Some,
|
||||||
None = None,
|
None = None,
|
||||||
Option = Option,
|
Option = Option,
|
||||||
}
|
}
|
||||||
|
|
121
lib/future.luau
121
lib/future.luau
|
@ -73,26 +73,26 @@ export type Status = "initialized" | "pending" | "cancelled" | "ready"
|
||||||
|
|
||||||
]=]
|
]=]
|
||||||
export type Future<T> = typeof(Future) & {
|
export type Future<T> = typeof(Future) & {
|
||||||
_ret: T,
|
_ret: T,
|
||||||
_thread: thread,
|
_thread: thread,
|
||||||
_spawnEvt: Signal<()>,
|
_spawnEvt: Signal<()>,
|
||||||
_retEvt: Signal<T | Result<T, string>, Status>,
|
_retEvt: Signal<T | Result<T, string>, Status>,
|
||||||
_status: Status,
|
_status: Status,
|
||||||
}
|
}
|
||||||
|
|
||||||
local function _constructor<T>(fn: (Signal<()>, Signal<T, Status>) -> ())
|
local function _constructor<T>(fn: (Signal<()>, Signal<T, Status>) -> ())
|
||||||
return setmetatable(
|
return setmetatable(
|
||||||
{
|
{
|
||||||
_thread = coroutine.create(fn),
|
_thread = coroutine.create(fn),
|
||||||
|
|
||||||
_spawnEvt = Signal.new(),
|
_spawnEvt = Signal.new(),
|
||||||
_retEvt = Signal.new(),
|
_retEvt = Signal.new(),
|
||||||
_status = "initialized",
|
_status = "initialized",
|
||||||
} :: Future<T>,
|
} :: Future<T>,
|
||||||
{
|
{
|
||||||
__index = Future,
|
__index = Future,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -110,12 +110,14 @@ end
|
||||||
@return Future<T> -- The constructed future
|
@return Future<T> -- The constructed future
|
||||||
]=]
|
]=]
|
||||||
function Future.new<T>(fn: (...any) -> T, args: { any })
|
function Future.new<T>(fn: (...any) -> T, args: { any })
|
||||||
return _constructor(function(spawnEvt: Signal<()>, retEvt: Signal<T, Status>)
|
return _constructor(
|
||||||
spawnEvt:Fire()
|
function(spawnEvt: Signal<()>, retEvt: Signal<T, Status>)
|
||||||
|
spawnEvt:Fire()
|
||||||
|
|
||||||
local ret = fn(table.unpack(args))
|
local ret = fn(table.unpack(args))
|
||||||
retEvt:Fire(ret, "ready")
|
retEvt:Fire(ret, "ready")
|
||||||
end)
|
end
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -128,13 +130,18 @@ end
|
||||||
@return Future<Result<T>> -- The constructed future
|
@return Future<Result<T>> -- The constructed future
|
||||||
]=]
|
]=]
|
||||||
function Future.try<T>(fn: (...any) -> T, args: { any })
|
function Future.try<T>(fn: (...any) -> T, args: { any })
|
||||||
return _constructor(function(spawnEvt: Signal<()>, retEvt: Signal<Result<T, string>, Status>)
|
return _constructor(
|
||||||
spawnEvt:Fire()
|
function(
|
||||||
|
spawnEvt: Signal<()>,
|
||||||
|
retEvt: Signal<Result<T, string>, Status>
|
||||||
|
)
|
||||||
|
spawnEvt:Fire()
|
||||||
|
|
||||||
local ok, ret = pcall(fn, table.unpack(args))
|
local ok, ret = pcall(fn, table.unpack(args))
|
||||||
local res: Result<T, string> = if ok then Ok(ret) else Err(ret)
|
local res: Result<T, string> = if ok then Ok(ret) else Err(ret)
|
||||||
retEvt:Fire(res, "ready")
|
retEvt:Fire(res, "ready")
|
||||||
end)
|
end
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -146,33 +153,33 @@ end
|
||||||
@return (Status, Option<T>) -- Returns the [Status] and an optional return if completed
|
@return (Status, Option<T>) -- Returns the [Status] and an optional return if completed
|
||||||
]=]
|
]=]
|
||||||
function Future.poll<T>(self: Future<T>): (Status, Option<T>)
|
function Future.poll<T>(self: Future<T>): (Status, Option<T>)
|
||||||
if self._status == "initialized" then
|
if self._status == "initialized" then
|
||||||
self._retEvt:Connect(function(firedRet, status: Status)
|
self._retEvt:Connect(function(firedRet, status: Status)
|
||||||
self._status = status
|
self._status = status
|
||||||
self._ret = firedRet
|
self._ret = firedRet
|
||||||
|
|
||||||
-- Cleanup
|
-- Cleanup
|
||||||
coroutine.yield(self._thread)
|
coroutine.yield(self._thread)
|
||||||
coroutine.close(self._thread)
|
coroutine.close(self._thread)
|
||||||
|
|
||||||
self._spawnEvt:DisconnectAll()
|
self._spawnEvt:DisconnectAll()
|
||||||
self._retEvt:DisconnectAll()
|
self._retEvt:DisconnectAll()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
self._spawnEvt:Connect(function()
|
self._spawnEvt:Connect(function()
|
||||||
self._status = "pending"
|
self._status = "pending"
|
||||||
end)
|
end)
|
||||||
|
|
||||||
coroutine.resume(self._thread, self._spawnEvt, self._retEvt)
|
coroutine.resume(self._thread, self._spawnEvt, self._retEvt)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self._status == "pending" then
|
if self._status == "pending" then
|
||||||
-- Just wait a bit more for the signal to fire
|
-- Just wait a bit more for the signal to fire
|
||||||
task.wait(0.01)
|
task.wait(0.01)
|
||||||
end
|
end
|
||||||
|
|
||||||
local retOpt = if self._ret == nil then None() else Some(self._ret)
|
local retOpt = if self._ret == nil then None() else Some(self._ret)
|
||||||
return self._status, retOpt
|
return self._status, retOpt
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -183,8 +190,8 @@ end
|
||||||
@param self Future<T>
|
@param self Future<T>
|
||||||
]=]
|
]=]
|
||||||
function Future.cancel<T>(self: Future<T>)
|
function Future.cancel<T>(self: Future<T>)
|
||||||
self._retEvt:Fire(nil :: any, "cancelled")
|
self._retEvt:Fire(nil :: any, "cancelled")
|
||||||
self._status = "cancelled"
|
self._status = "cancelled"
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -197,14 +204,14 @@ end
|
||||||
@return T -- The value returned by the function on completion
|
@return T -- The value returned by the function on completion
|
||||||
]=]
|
]=]
|
||||||
function Future.await<T>(self: Future<T>): T
|
function Future.await<T>(self: Future<T>): T
|
||||||
while true do
|
while true do
|
||||||
local status: Status, ret: Option<T> = self:poll()
|
local status: Status, ret: Option<T> = self:poll()
|
||||||
|
|
||||||
if status == "ready" then
|
if status == "ready" then
|
||||||
-- Safe to unwrap, we know it must not be nil
|
-- Safe to unwrap, we know it must not be nil
|
||||||
return ret:unwrap()
|
return ret:unwrap()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return Future
|
return Future
|
||||||
|
|
338
lib/option.luau
338
lib/option.luau
|
@ -27,8 +27,8 @@ local tableEq = require("util").tableEq
|
||||||
local Option = {}
|
local Option = {}
|
||||||
|
|
||||||
export type Option<T> = typeof(Option) & {
|
export type Option<T> = typeof(Option) & {
|
||||||
_optValue: T?,
|
_optValue: T?,
|
||||||
typeId: "Option",
|
typeId: "Option",
|
||||||
}
|
}
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -37,7 +37,7 @@ export type Option<T> = typeof(Option) & {
|
||||||
No value.
|
No value.
|
||||||
]=]
|
]=]
|
||||||
function None<T>(): Option<T>
|
function None<T>(): Option<T>
|
||||||
return Option.new(nil) :: Option<T>
|
return Option.new(nil) :: Option<T>
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -46,7 +46,7 @@ end
|
||||||
Some value of type `T`.
|
Some value of type `T`.
|
||||||
]=]
|
]=]
|
||||||
function Some<T>(val: T): Option<T>
|
function Some<T>(val: T): Option<T>
|
||||||
return Option.new(val) :: Option<T>
|
return Option.new(val) :: Option<T>
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -58,46 +58,49 @@ end
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Option.new<T>(val: T?)
|
function Option.new<T>(val: T?)
|
||||||
return setmetatable(
|
return setmetatable(
|
||||||
{
|
{
|
||||||
_optValue = val,
|
_optValue = val,
|
||||||
typeId = "Option",
|
typeId = "Option",
|
||||||
} :: Option<T>,
|
} :: Option<T>,
|
||||||
{
|
{
|
||||||
__index = Option,
|
__index = Option,
|
||||||
__tostring = function<T>(self: Option<T>)
|
__tostring = function<T>(self: Option<T>)
|
||||||
if self._optValue == nil then
|
if self._optValue == nil then
|
||||||
return `{self.typeId}::None`
|
return `{self.typeId}::None`
|
||||||
else
|
else
|
||||||
return `{self.typeId}::Some({self._optValue})`
|
return `{self.typeId}::Some({self._optValue})`
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
__eq = function<T>(self: Option<T>, other: Option<T>): boolean
|
__eq = function<T>(self: Option<T>, other: Option<T>): boolean
|
||||||
if typeof(self._optValue) == "table" and typeof(other._optValue) == "table" then
|
if
|
||||||
return tableEq(self._optValue, other._optValue)
|
typeof(self._optValue) == "table"
|
||||||
else
|
and typeof(other._optValue) == "table"
|
||||||
return self._optValue == other._optValue
|
then
|
||||||
end
|
return tableEq(self._optValue, other._optValue)
|
||||||
end,
|
else
|
||||||
__lt = function<T>(self: Option<T>, other: Option<T>): boolean
|
return self._optValue == other._optValue
|
||||||
if self:isSome() and other:isSome() then
|
end
|
||||||
return (self._optValue :: any) < (other._optValue :: any)
|
end,
|
||||||
end
|
__lt = function<T>(self: Option<T>, other: Option<T>): boolean
|
||||||
|
if self:isSome() and other:isSome() then
|
||||||
|
return (self._optValue :: any) < (other._optValue :: any)
|
||||||
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end,
|
end,
|
||||||
__le = function<T>(self: Option<T>, other: Option<T>): boolean
|
__le = function<T>(self: Option<T>, other: Option<T>): boolean
|
||||||
if self:isSome() and other:isSome() then
|
if self:isSome() and other:isSome() then
|
||||||
return (self._optValue :: any) <= (other._optValue :: any)
|
return (self._optValue :: any) <= (other._optValue :: any)
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- TODO: Implement __iter, once iterators traits exist
|
-- TODO: Implement __iter, once iterators traits exist
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -109,7 +112,7 @@ end
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Option.isSome<T>(self: Option<T>): boolean
|
function Option.isSome<T>(self: Option<T>): boolean
|
||||||
return self._optValue ~= nil
|
return self._optValue ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -123,8 +126,8 @@ end
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Option.isSomeAnd<T>(self: Option<T>, op: (val: T) -> boolean): boolean
|
function Option.isSomeAnd<T>(self: Option<T>, op: (val: T) -> boolean): boolean
|
||||||
-- We know that it's not None, so this is fine
|
-- We know that it's not None, so this is fine
|
||||||
return self:isSome() and op(self._optValue :: T)
|
return self:isSome() and op(self._optValue :: T)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -136,7 +139,7 @@ end
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Option.isNone<T>(self: Option<T>): boolean
|
function Option.isNone<T>(self: Option<T>): boolean
|
||||||
return not self:isSome()
|
return not self:isSome()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -161,11 +164,13 @@ end
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Option.expect<T>(self: Option<T>, msg: string): T | never
|
function Option.expect<T>(self: Option<T>, msg: string): T | never
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return self._optValue :: T
|
return self._optValue :: T
|
||||||
end
|
end
|
||||||
|
|
||||||
return error(`panic: {msg}; expected Option to be type Option::Some(T), got Option::None`)
|
return error(
|
||||||
|
`panic: {msg}; expected Option to be type Option::Some(T), got Option::None`
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -181,11 +186,11 @@ end
|
||||||
@return T | never
|
@return T | never
|
||||||
]=]
|
]=]
|
||||||
function Option.unwrap<T>(self: Option<T>): T | never
|
function Option.unwrap<T>(self: Option<T>): T | never
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return self._optValue :: T
|
return self._optValue :: T
|
||||||
end
|
end
|
||||||
|
|
||||||
return error("called `Option:unwrap()` on a `None` value")
|
return error("called `Option:unwrap()` on a `None` value")
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -207,11 +212,11 @@ end
|
||||||
@return T
|
@return T
|
||||||
]=]
|
]=]
|
||||||
function Option.unwrapOr<T>(self: Option<T>, default: T): T
|
function Option.unwrapOr<T>(self: Option<T>, default: T): T
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return self._optValue :: T
|
return self._optValue :: T
|
||||||
end
|
end
|
||||||
|
|
||||||
return default
|
return default
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -234,11 +239,11 @@ end
|
||||||
@return T
|
@return T
|
||||||
]=]
|
]=]
|
||||||
function Option.unwrapOrElse<T>(self: Option<T>, default: () -> T): T
|
function Option.unwrapOrElse<T>(self: Option<T>, default: () -> T): T
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return self._optValue :: T
|
return self._optValue :: T
|
||||||
end
|
end
|
||||||
|
|
||||||
return default()
|
return default()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -266,17 +271,17 @@ end
|
||||||
@return Option<U>
|
@return Option<U>
|
||||||
]=]
|
]=]
|
||||||
function Option.map<T, U>(self: Option<T>, op: (x: T) -> U?): Option<U>
|
function Option.map<T, U>(self: Option<T>, op: (x: T) -> U?): Option<U>
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
local val = op(self._optValue :: T)
|
local val = op(self._optValue :: T)
|
||||||
|
|
||||||
if val == nil then
|
if val == nil then
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
return Some(val)
|
return Some(val)
|
||||||
end
|
end
|
||||||
|
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -303,11 +308,11 @@ end
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Option.inspect<T>(self: Option<T>, op: (x: T) -> ()): Option<T>
|
function Option.inspect<T>(self: Option<T>, op: (x: T) -> ()): Option<T>
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
op(self._optValue :: T)
|
op(self._optValue :: T)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -333,11 +338,11 @@ end
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Option.mapOr<T, U>(self: Option<T>, default: U, op: (val: T) -> U)
|
function Option.mapOr<T, U>(self: Option<T>, default: U, op: (val: T) -> U)
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return op(self._optValue :: T)
|
return op(self._optValue :: T)
|
||||||
end
|
end
|
||||||
|
|
||||||
return default
|
return default
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -371,17 +376,21 @@ end
|
||||||
@param op (val: T) -> U -- The function to apply
|
@param op (val: T) -> U -- The function to apply
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Option.mapOrElse<T, U>(self: Option<T>, default: () -> U, op: (val: T) -> U): U
|
function Option.mapOrElse<T, U>(
|
||||||
if self:isSome() then
|
self: Option<T>,
|
||||||
return op(self._optValue :: T)
|
default: () -> U,
|
||||||
end
|
op: (val: T) -> U
|
||||||
|
): U
|
||||||
|
if self:isSome() then
|
||||||
|
return op(self._optValue :: T)
|
||||||
|
end
|
||||||
|
|
||||||
return default()
|
return default()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: Iterator traits
|
-- TODO: Iterator traits
|
||||||
function Option.iter(): never
|
function Option.iter(): never
|
||||||
return error("Unimplemented: `Option:iter()`")
|
return error("Unimplemented: `Option:iter()`")
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -415,11 +424,11 @@ end
|
||||||
@return Option<U>
|
@return Option<U>
|
||||||
]=]
|
]=]
|
||||||
function Option.and_<T, U>(self: Option<T>, optb: Option<U>): Option<U>
|
function Option.and_<T, U>(self: Option<T>, optb: Option<U>): Option<U>
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return optb
|
return optb
|
||||||
end
|
end
|
||||||
|
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -462,11 +471,11 @@ end
|
||||||
@return Option<U>
|
@return Option<U>
|
||||||
]=]
|
]=]
|
||||||
function Option.andThen<T, U>(self: Option<T>, op: (val: T) -> Option<U>): Option<U>
|
function Option.andThen<T, U>(self: Option<T>, op: (val: T) -> Option<U>): Option<U>
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return op(self._optValue :: T)
|
return op(self._optValue :: T)
|
||||||
end
|
end
|
||||||
|
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -492,14 +501,17 @@ end
|
||||||
@param predicate (val: T) -> boolean -- The predicate function which must match an element
|
@param predicate (val: T) -> boolean -- The predicate function which must match an element
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Option.filter<T>(self: Option<T>, predicate: (val: T) -> boolean): Option<T>
|
function Option.filter<T>(
|
||||||
if self:isSome() then
|
self: Option<T>,
|
||||||
if predicate(self._optValue :: T) then
|
predicate: (val: T) -> boolean
|
||||||
return self
|
): Option<T>
|
||||||
end
|
if self:isSome() then
|
||||||
end
|
if predicate(self._optValue :: T) then
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -534,11 +546,11 @@ end
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Option.or_<T>(self: Option<T>, optb: Option<T>): Option<T>
|
function Option.or_<T>(self: Option<T>, optb: Option<T>): Option<T>
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
return optb
|
return optb
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -564,11 +576,11 @@ end
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Option.orElse<T>(self: Option<T>, op: () -> Option<T>): Option<T>
|
function Option.orElse<T>(self: Option<T>, op: () -> Option<T>): Option<T>
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
return op()
|
return op()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -600,17 +612,17 @@ end
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Option.xor<T>(self: Option<T>, optb: Option<T>): Option<T>
|
function Option.xor<T>(self: Option<T>, optb: Option<T>): Option<T>
|
||||||
if self:isSome() and optb:isSome() then
|
if self:isSome() and optb:isSome() then
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return self
|
return self
|
||||||
elseif optb:isSome() then
|
elseif optb:isSome() then
|
||||||
return optb
|
return optb
|
||||||
end
|
end
|
||||||
|
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -638,8 +650,8 @@ end
|
||||||
@return T
|
@return T
|
||||||
]=]
|
]=]
|
||||||
function Option.insert<T>(self: Option<T>, val: T): T
|
function Option.insert<T>(self: Option<T>, val: T): T
|
||||||
self._optValue = val
|
self._optValue = val
|
||||||
return self._optValue :: T
|
return self._optValue :: T
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -667,11 +679,11 @@ end
|
||||||
@return T
|
@return T
|
||||||
]=]
|
]=]
|
||||||
function Option.getOrInsert<T>(self: Option<T>, val: T): T
|
function Option.getOrInsert<T>(self: Option<T>, val: T): T
|
||||||
if self:isNone() then
|
if self:isNone() then
|
||||||
self._optValue = val
|
self._optValue = val
|
||||||
end
|
end
|
||||||
|
|
||||||
return self._optValue :: T
|
return self._optValue :: T
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -695,13 +707,13 @@ end
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Option.take<T>(self: Option<T>): Option<T>
|
function Option.take<T>(self: Option<T>): Option<T>
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
local val = self._optValue :: T
|
local val = self._optValue :: T
|
||||||
self._optValue = nil
|
self._optValue = nil
|
||||||
return Some(val)
|
return Some(val)
|
||||||
end
|
end
|
||||||
|
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -728,14 +740,14 @@ end
|
||||||
@return Option<T>
|
@return Option<T>
|
||||||
]=]
|
]=]
|
||||||
function Option.replace<T>(self: Option<T>, val: T): Option<T>
|
function Option.replace<T>(self: Option<T>, val: T): Option<T>
|
||||||
local current: Option<T> = self
|
local current: Option<T> = self
|
||||||
self._optValue = val
|
self._optValue = val
|
||||||
|
|
||||||
if current:isNone() then
|
if current:isNone() then
|
||||||
return current
|
return current
|
||||||
end
|
end
|
||||||
|
|
||||||
return Some(current._optValue :: T)
|
return Some(current._optValue :: T)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -757,11 +769,11 @@ end
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Option.contains<T>(self: Option<T>, val: T): boolean
|
function Option.contains<T>(self: Option<T>, val: T): boolean
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
return self._optValue == val
|
return self._optValue == val
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -786,11 +798,11 @@ end
|
||||||
@return Option<{T | U}>
|
@return Option<{T | U}>
|
||||||
]=]
|
]=]
|
||||||
function Option.zip<T, U>(self: Option<T>, other: Option<U>): Option<{ T | U }>
|
function Option.zip<T, U>(self: Option<T>, other: Option<U>): Option<{ T | U }>
|
||||||
if self:isSome() and other:isSome() then
|
if self:isSome() and other:isSome() then
|
||||||
return Some({ self._optValue, other._optValue })
|
return Some { self._optValue, other._optValue }
|
||||||
end
|
end
|
||||||
|
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -829,16 +841,20 @@ end
|
||||||
@param op (x: T, y: U) -> R?
|
@param op (x: T, y: U) -> R?
|
||||||
@return Option<R>
|
@return Option<R>
|
||||||
]=]
|
]=]
|
||||||
function Option.zipWith<T, U, R>(self: Option<T>, other: Option<U>, op: (x: T, y: U) -> R?): Option<R>
|
function Option.zipWith<T, U, R>(
|
||||||
if self:isSome() and other:isSome() then
|
self: Option<T>,
|
||||||
local computed = op(self._optValue :: T, other._optValue :: U)
|
other: Option<U>,
|
||||||
|
op: (x: T, y: U) -> R?
|
||||||
|
): Option<R>
|
||||||
|
if self:isSome() and other:isSome() then
|
||||||
|
local computed = op(self._optValue :: T, other._optValue :: U)
|
||||||
|
|
||||||
if computed ~= nil then
|
if computed ~= nil then
|
||||||
return Some(computed :: R)
|
return Some(computed :: R)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return None()
|
return None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -861,13 +877,17 @@ end
|
||||||
@return (Option<A>, Option<B>)
|
@return (Option<A>, Option<B>)
|
||||||
]=]
|
]=]
|
||||||
function Option.unzip<T, A, B>(self: Option<T>): (Option<A>, Option<B>)
|
function Option.unzip<T, A, B>(self: Option<T>): (Option<A>, Option<B>)
|
||||||
if self:isSome() then
|
if self:isSome() then
|
||||||
if self:isSome() and typeof(self._optValue) == "table" and #self._optValue == 2 then
|
if
|
||||||
return Some(self._optValue[1] :: A), Some(self._optValue[2] :: B)
|
self:isSome()
|
||||||
end
|
and typeof(self._optValue) == "table"
|
||||||
end
|
and #self._optValue == 2
|
||||||
|
then
|
||||||
|
return Some(self._optValue[1] :: A), Some(self._optValue[2] :: B)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return None(), None()
|
return None(), None()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -887,7 +907,7 @@ end
|
||||||
@return T?
|
@return T?
|
||||||
]=]
|
]=]
|
||||||
function Option.unwrapUnchecked<T>(self: Option<T>): T?
|
function Option.unwrapUnchecked<T>(self: Option<T>): T?
|
||||||
return self._optValue
|
return self._optValue
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -908,11 +928,11 @@ end
|
||||||
@return string
|
@return string
|
||||||
]=]
|
]=]
|
||||||
function Option.display<T>(self: Option<T>): string
|
function Option.display<T>(self: Option<T>): string
|
||||||
return tostring(self)
|
return tostring(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Option = Option,
|
Option = Option,
|
||||||
Some = Some,
|
Some = Some,
|
||||||
None = None,
|
None = None,
|
||||||
}
|
}
|
||||||
|
|
287
lib/result.luau
287
lib/result.luau
|
@ -66,9 +66,9 @@ local tableEq = require("util").tableEq
|
||||||
local Result = {}
|
local Result = {}
|
||||||
|
|
||||||
export type Result<T, E> = typeof(Result) & {
|
export type Result<T, E> = typeof(Result) & {
|
||||||
_value: T,
|
_value: T,
|
||||||
_error: E,
|
_error: E,
|
||||||
typeId: "Result",
|
typeId: "Result",
|
||||||
}
|
}
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -80,7 +80,7 @@ export type Result<T, E> = typeof(Result) & {
|
||||||
@return Result<T, E>
|
@return Result<T, E>
|
||||||
]=]
|
]=]
|
||||||
function Ok<T, E>(val: T): Result<T, E>
|
function Ok<T, E>(val: T): Result<T, E>
|
||||||
return Result.new(val, (nil :: unknown) :: E)
|
return Result.new(val, (nil :: unknown) :: E)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -92,7 +92,7 @@ end
|
||||||
@return Result<T, E>
|
@return Result<T, E>
|
||||||
]=]
|
]=]
|
||||||
function Err<T, E>(err: E): Result<T, E>
|
function Err<T, E>(err: E): Result<T, E>
|
||||||
return Result.new((nil :: unknown) :: T, err)
|
return Result.new((nil :: unknown) :: T, err)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -107,42 +107,44 @@ end
|
||||||
@return Result<T, E>
|
@return Result<T, E>
|
||||||
]=]
|
]=]
|
||||||
function Result.new<T, E>(val: T, err: E)
|
function Result.new<T, E>(val: T, err: E)
|
||||||
return setmetatable(
|
return setmetatable(
|
||||||
{
|
{
|
||||||
_value = val,
|
_value = val,
|
||||||
_error = err,
|
_error = err,
|
||||||
typeId = "Result",
|
typeId = "Result",
|
||||||
} :: Result<T, E>,
|
} :: Result<T, E>,
|
||||||
{
|
{
|
||||||
__index = Result,
|
__index = Result,
|
||||||
__tostring = function<T, E>(self: Result<T, E>)
|
__tostring = function<T, E>(self: Result<T, E>)
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return `{self.typeId}::Ok({self._value})`
|
return `{self.typeId}::Ok({self._value})`
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:isErr() then
|
if self:isErr() then
|
||||||
return `{self.typeId}::Err({self._error})`
|
return `{self.typeId}::Err({self._error})`
|
||||||
end
|
end
|
||||||
|
|
||||||
return `{self.typeId}<T, E>`
|
return `{self.typeId}<T, E>`
|
||||||
end,
|
end,
|
||||||
__eq = function<T, E>(self: Result<T, E>, other: Result<T, E>)
|
__eq = function<T, E>(self: Result<T, E>, other: Result<T, E>)
|
||||||
if
|
if
|
||||||
typeof(self._value) ~= "table"
|
typeof(self._value) ~= "table"
|
||||||
and typeof(self._error) ~= "table"
|
and typeof(self._error) ~= "table"
|
||||||
and typeof(other._value) ~= "table"
|
and typeof(other._value) ~= "table"
|
||||||
and typeof(other._error) ~= "table"
|
and typeof(other._error) ~= "table"
|
||||||
then
|
then
|
||||||
return self._value == other._value and self._error == other._error
|
return self._value == other._value
|
||||||
end
|
and self._error == other._error
|
||||||
|
end
|
||||||
|
|
||||||
return tableEq(self._value, other._value) and tableEq(self._error, other._error)
|
return tableEq(self._value, other._value)
|
||||||
end,
|
and tableEq(self._error, other._error)
|
||||||
|
end,
|
||||||
|
|
||||||
-- TODO: Implement equality and arithmetic metamethods
|
-- TODO: Implement equality and arithmetic metamethods
|
||||||
-- TODO: Implement __iter, once iterators traits exist
|
-- TODO: Implement __iter, once iterators traits exist
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -162,11 +164,11 @@ end
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Result.isOk<T, E>(self: Result<T, E>): boolean
|
function Result.isOk<T, E>(self: Result<T, E>): boolean
|
||||||
if self._value == nil then
|
if self._value == nil then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -190,8 +192,11 @@ end
|
||||||
@param predicate (val: T?) -> boolean
|
@param predicate (val: T?) -> boolean
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Result.isOkAnd<T, E>(self: Result<T, E>, predicate: (val: T?) -> boolean): boolean
|
function Result.isOkAnd<T, E>(
|
||||||
return self:isOk() and predicate(self._value)
|
self: Result<T, E>,
|
||||||
|
predicate: (val: T?) -> boolean
|
||||||
|
): boolean
|
||||||
|
return self:isOk() and predicate(self._value)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -211,7 +216,7 @@ end
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Result.isErr<T, E>(self: Result<T, E>)
|
function Result.isErr<T, E>(self: Result<T, E>)
|
||||||
return not self:isOk()
|
return not self:isOk()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -235,12 +240,15 @@ end
|
||||||
@param predicate (val: T?) -> boolean
|
@param predicate (val: T?) -> boolean
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Result.isErrAnd<T, E>(self: Result<T, E>, predicate: (val: E) -> boolean): boolean
|
function Result.isErrAnd<T, E>(
|
||||||
if self:isErr() then
|
self: Result<T, E>,
|
||||||
return predicate(self._error)
|
predicate: (val: E) -> boolean
|
||||||
end
|
): boolean
|
||||||
|
if self:isErr() then
|
||||||
|
return predicate(self._error)
|
||||||
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -280,11 +288,11 @@ end
|
||||||
@return Result<U, E>
|
@return Result<U, E>
|
||||||
]=]
|
]=]
|
||||||
function Result.map<T, E, U>(self: Result<T, E>, op: (val: T) -> U): Result<U, E>
|
function Result.map<T, E, U>(self: Result<T, E>, op: (val: T) -> U): Result<U, E>
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return Result.new(op(self._value), self._error) :: Result<U, E>
|
return Result.new(op(self._value), self._error) :: Result<U, E>
|
||||||
end
|
end
|
||||||
|
|
||||||
return Err(self._error)
|
return Err(self._error)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -311,11 +319,11 @@ end
|
||||||
@return U
|
@return U
|
||||||
]=]
|
]=]
|
||||||
function Result.mapOr<T, E, U>(self: Result<T, E>, default: U, op: (val: T) -> U): U
|
function Result.mapOr<T, E, U>(self: Result<T, E>, default: U, op: (val: T) -> U): U
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return op(self._value)
|
return op(self._value)
|
||||||
end
|
end
|
||||||
|
|
||||||
return default
|
return default
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -339,12 +347,16 @@ end
|
||||||
@param op (val: T) -> U
|
@param op (val: T) -> U
|
||||||
@return U
|
@return U
|
||||||
]=]
|
]=]
|
||||||
function Result.mapOrElse<T, E, U>(self: Result<T, E>, default: (val: E) -> U, op: (val: T) -> U): U
|
function Result.mapOrElse<T, E, U>(
|
||||||
if self:isOk() then
|
self: Result<T, E>,
|
||||||
return op(self._value)
|
default: (val: E) -> U,
|
||||||
end
|
op: (val: T) -> U
|
||||||
|
): U
|
||||||
|
if self:isOk() then
|
||||||
|
return op(self._value)
|
||||||
|
end
|
||||||
|
|
||||||
return default(self._error)
|
return default(self._error)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -373,11 +385,11 @@ end
|
||||||
@return Result<T, F>
|
@return Result<T, F>
|
||||||
]=]
|
]=]
|
||||||
function Result.mapErr<T, E, F>(self: Result<T, E>, op: (val: E) -> F): Result<T, F>
|
function Result.mapErr<T, E, F>(self: Result<T, E>, op: (val: E) -> F): Result<T, F>
|
||||||
if self:isErr() then
|
if self:isErr() then
|
||||||
return Result.new(self._value, op(self._error))
|
return Result.new(self._value, op(self._error))
|
||||||
end
|
end
|
||||||
|
|
||||||
return Ok(self._value)
|
return Ok(self._value)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -409,11 +421,11 @@ end
|
||||||
@return Result<T, E>
|
@return Result<T, E>
|
||||||
]=]
|
]=]
|
||||||
function Result.inspect<T, E>(self: Result<T, E>, op: (val: T) -> ()): Result<T, E>
|
function Result.inspect<T, E>(self: Result<T, E>, op: (val: T) -> ()): Result<T, E>
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
op(self._value)
|
op(self._value)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -445,17 +457,17 @@ end
|
||||||
@return Result<T, E>
|
@return Result<T, E>
|
||||||
]=]
|
]=]
|
||||||
function Result.inspectErr<T, E>(self: Result<T, E>, op: (val: E) -> ()): Result<T, E>
|
function Result.inspectErr<T, E>(self: Result<T, E>, op: (val: E) -> ()): Result<T, E>
|
||||||
if self:isErr() then
|
if self:isErr() then
|
||||||
op(self._error)
|
op(self._error)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: Iterator traits
|
-- TODO: Iterator traits
|
||||||
-- selene: allow(unused_variable)
|
-- selene: allow(unused_variable)
|
||||||
function Result.iter<T, E>(self: Result<T, E>): never
|
function Result.iter<T, E>(self: Result<T, E>): never
|
||||||
return error("Unimplemented: `Result:iter()`")
|
return error("Unimplemented: `Result:iter()`")
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -505,11 +517,11 @@ end
|
||||||
@return T | never
|
@return T | never
|
||||||
]=]
|
]=]
|
||||||
function Result.expect<T, E>(self: Result<T, E>, msg: string): T | never
|
function Result.expect<T, E>(self: Result<T, E>, msg: string): T | never
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return self._value
|
return self._value
|
||||||
end
|
end
|
||||||
|
|
||||||
return error(`panic: {msg}; {self._error}`)
|
return error(`panic: {msg}; {self._error}`)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -533,17 +545,19 @@ end
|
||||||
@param self Result<T, E>
|
@param self Result<T, E>
|
||||||
]=]
|
]=]
|
||||||
function Result.unwrap<T, E>(self: Result<T, E>): T | never
|
function Result.unwrap<T, E>(self: Result<T, E>): T | never
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return self._value
|
return self._value
|
||||||
end
|
end
|
||||||
|
|
||||||
return error(`panic: \`Result:unwrap()\` called on an \`Err\` value: {self._error}`)
|
return error(
|
||||||
|
`panic: \`Result:unwrap()\` called on an \`Err\` value: {self._error}`
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: default values for types
|
-- TODO: default values for types
|
||||||
-- selene: allow(unused_variable)
|
-- selene: allow(unused_variable)
|
||||||
function Result.unwrapOrDefault<T, E>(self: Result<T, E>): never
|
function Result.unwrapOrDefault<T, E>(self: Result<T, E>): never
|
||||||
return error("Unimplemented: `Result:unwrapOrDefault()`")
|
return error("Unimplemented: `Result:unwrapOrDefault()`")
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -563,11 +577,11 @@ end
|
||||||
@return E | never
|
@return E | never
|
||||||
]=]
|
]=]
|
||||||
function Result.expectErr<T, E>(self: Result<T, E>, msg: string): E | never
|
function Result.expectErr<T, E>(self: Result<T, E>, msg: string): E | never
|
||||||
if self:isErr() then
|
if self:isErr() then
|
||||||
return self._error
|
return self._error
|
||||||
end
|
end
|
||||||
|
|
||||||
return error(`panic: {msg}; {self._error}`)
|
return error(`panic: {msg}; {self._error}`)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -590,21 +604,23 @@ end
|
||||||
@return E | never
|
@return E | never
|
||||||
]=]
|
]=]
|
||||||
function Result.unwrapErr<T, E>(self: Result<T, E>): E | never
|
function Result.unwrapErr<T, E>(self: Result<T, E>): E | never
|
||||||
if self:isErr() then
|
if self:isErr() then
|
||||||
return self._error
|
return self._error
|
||||||
end
|
end
|
||||||
|
|
||||||
return error(`panic: \`Result:unwrapErr()\` called on an \`Ok\` value: {self._value}`)
|
return error(
|
||||||
|
`panic: \`Result:unwrapErr()\` called on an \`Ok\` value: {self._value}`
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: How the fuck do I implement this?
|
-- TODO: How the fuck do I implement this?
|
||||||
-- selene: allow(unused_variable)
|
-- selene: allow(unused_variable)
|
||||||
function Result.intoOk<T, E>(self: Result<T, E>): never
|
function Result.intoOk<T, E>(self: Result<T, E>): never
|
||||||
return error("Unimplemented: `Result:intoOk()`")
|
return error("Unimplemented: `Result:intoOk()`")
|
||||||
end
|
end
|
||||||
-- selene: allow(unused_variable)
|
-- selene: allow(unused_variable)
|
||||||
function Result.intoErr<T, E>(self: Result<T, E>): never
|
function Result.intoErr<T, E>(self: Result<T, E>): never
|
||||||
return error("Unimplemented: `Result:intoErr()`")
|
return error("Unimplemented: `Result:intoErr()`")
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -636,11 +652,11 @@ end
|
||||||
@return Result<U, E>
|
@return Result<U, E>
|
||||||
]=]
|
]=]
|
||||||
function Result.and_<T, E, U>(self: Result<T, E>, res: Result<U, E>): Result<U, E>
|
function Result.and_<T, E, U>(self: Result<T, E>, res: Result<U, E>): Result<U, E>
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
return Err(self._error)
|
return Err(self._error)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -674,11 +690,11 @@ end
|
||||||
@return Result<U, E>
|
@return Result<U, E>
|
||||||
]=]
|
]=]
|
||||||
function Result.andThen<T, E, U>(self: Result<T, E>, op: (...any) -> any): Result<U, E>
|
function Result.andThen<T, E, U>(self: Result<T, E>, op: (...any) -> any): Result<U, E>
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return op(self._value)
|
return op(self._value)
|
||||||
end
|
end
|
||||||
|
|
||||||
return Err(self._error) :: Result<U, E>
|
return Err(self._error) :: Result<U, E>
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -713,15 +729,15 @@ end
|
||||||
@return Result<T, F> | never
|
@return Result<T, F> | never
|
||||||
]=]
|
]=]
|
||||||
function Result.or_<T, E, F>(self: Result<T, E>, res: Result<T, F>): Result<T, F> | never
|
function Result.or_<T, E, F>(self: Result<T, E>, res: Result<T, F>): Result<T, F> | never
|
||||||
if self:isErr() then
|
if self:isErr() then
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return Ok(self._value) :: Result<T, F>
|
return Ok(self._value) :: Result<T, F>
|
||||||
end
|
end
|
||||||
|
|
||||||
return error("called `Result:or()` with an invalid value")
|
return error("called `Result:or()` with an invalid value")
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -752,12 +768,15 @@ end
|
||||||
@param op (x: E) -> Result<T, U>
|
@param op (x: E) -> Result<T, U>
|
||||||
@return Result<T, U>
|
@return Result<T, U>
|
||||||
]=]
|
]=]
|
||||||
function Result.orElse<T, E, U>(self: Result<T, E>, op: (x: E) -> Result<T, U>): Result<T, U>
|
function Result.orElse<T, E, U>(
|
||||||
if self:isErr() then
|
self: Result<T, E>,
|
||||||
return op(self._error)
|
op: (x: E) -> Result<T, U>
|
||||||
end
|
): Result<T, U>
|
||||||
|
if self:isErr() then
|
||||||
|
return op(self._error)
|
||||||
|
end
|
||||||
|
|
||||||
return Ok(self._value)
|
return Ok(self._value)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -783,11 +802,11 @@ end
|
||||||
@return T
|
@return T
|
||||||
]=]
|
]=]
|
||||||
function Result.unwrapOr<T, E>(self: Result<T, E>, default: T): T
|
function Result.unwrapOr<T, E>(self: Result<T, E>, default: T): T
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return self._value
|
return self._value
|
||||||
end
|
end
|
||||||
|
|
||||||
return default
|
return default
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -809,11 +828,11 @@ end
|
||||||
@return T
|
@return T
|
||||||
]=]
|
]=]
|
||||||
function Result.unwrapOrElse<T, E>(self: Result<T, E>, op: (x: E) -> T): T
|
function Result.unwrapOrElse<T, E>(self: Result<T, E>, op: (x: E) -> T): T
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return self._value
|
return self._value
|
||||||
end
|
end
|
||||||
|
|
||||||
return op(self._error)
|
return op(self._error)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -837,11 +856,11 @@ end
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Result.contains<T, E>(self: Result<T, E>, val: T): boolean
|
function Result.contains<T, E>(self: Result<T, E>, val: T): boolean
|
||||||
if self:isOk() then
|
if self:isOk() then
|
||||||
return self._value == val
|
return self._value == val
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -865,11 +884,11 @@ end
|
||||||
@return boolean
|
@return boolean
|
||||||
]=]
|
]=]
|
||||||
function Result.containsErr<T, E>(self: Result<T, E>, err: E): boolean
|
function Result.containsErr<T, E>(self: Result<T, E>, err: E): boolean
|
||||||
if self:isErr() then
|
if self:isErr() then
|
||||||
return self._error == err
|
return self._error == err
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
|
@ -890,11 +909,11 @@ end
|
||||||
@return string
|
@return string
|
||||||
]=]
|
]=]
|
||||||
function Result.display<T, E>(self: Result<T, E>): string
|
function Result.display<T, E>(self: Result<T, E>): string
|
||||||
return tostring(self)
|
return tostring(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Ok = Ok,
|
Ok = Ok,
|
||||||
Err = Err,
|
Err = Err,
|
||||||
Result = Result,
|
Result = Result,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
-- From https://gist.github.com/sapphyrus/fd9aeb871e3ce966cc4b0b969f62f539
|
-- From https://gist.github.com/sapphyrus/fd9aeb871e3ce966cc4b0b969f62f539
|
||||||
local function tableEq(tbl1, tbl2)
|
local function tableEq(tbl1, tbl2)
|
||||||
if tbl1 == tbl2 then
|
if tbl1 == tbl2 then
|
||||||
return true
|
return true
|
||||||
elseif type(tbl1) == "table" and type(tbl2) == "table" then
|
elseif type(tbl1) == "table" and type(tbl2) == "table" then
|
||||||
for key1, value1 in pairs(tbl1) do
|
for key1, value1 in pairs(tbl1) do
|
||||||
local value2 = tbl2[key1]
|
local value2 = tbl2[key1]
|
||||||
|
|
||||||
if value2 == nil then
|
if value2 == nil then
|
||||||
-- avoid the type call for missing keys in tbl2 by directly comparing with nil
|
-- avoid the type call for missing keys in tbl2 by directly comparing with nil
|
||||||
return false
|
return false
|
||||||
elseif value1 ~= value2 then
|
elseif value1 ~= value2 then
|
||||||
if type(value1) == "table" and type(value2) == "table" then
|
if type(value1) == "table" and type(value2) == "table" then
|
||||||
if not tableEq(value1, value2) then
|
if not tableEq(value1, value2) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check for missing keys in tbl1
|
-- check for missing keys in tbl1
|
||||||
for key2, _ in pairs(tbl2) do
|
for key2, _ in pairs(tbl2) do
|
||||||
if tbl1[key2] == nil then
|
if tbl1[key2] == nil then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tableEq = tableEq,
|
tableEq = tableEq,
|
||||||
}
|
}
|
||||||
|
|
14
mod.luau
14
mod.luau
|
@ -1,14 +1,16 @@
|
||||||
local luau = require("@lune/luau")
|
|
||||||
local fs = require("@lune/fs")
|
local fs = require("@lune/fs")
|
||||||
|
local luau = require("@lune/luau")
|
||||||
|
|
||||||
local SIGNAL_PATH = "Packages/_Index/ffrostflame_luausignal@0.2.4/luausignal/src/init.luau"
|
local SIGNAL_PATH =
|
||||||
|
"Packages/_Index/ffrostflame_luausignal@0.2.4/luausignal/src/init.luau"
|
||||||
local _signal = require(SIGNAL_PATH)
|
local _signal = require(SIGNAL_PATH)
|
||||||
export type Signal<T...> = _signal.luauSignal<T...>
|
export type Signal<T...> = _signal.luauSignal<T...>
|
||||||
local signal: {
|
local signal: {
|
||||||
new: <T...>() -> Signal<T...>,
|
new: <T...>() -> Signal<T...>,
|
||||||
} =
|
} = luau.load(
|
||||||
luau.load('local task = require("@lune/task")\n' .. fs.readFile(SIGNAL_PATH))()
|
'local task = require("@lune/task")\n' .. fs.readFile(SIGNAL_PATH)
|
||||||
|
)()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
signal = signal,
|
signal = signal,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue