mirror of
https://github.com/luau-lang/rfcs.git
synced 2025-04-10 13:30:55 +01:00
RFC: Result type function
This commit is contained in:
parent
03608c7519
commit
4f3753df13
1 changed files with 121 additions and 0 deletions
121
docs/result-type-operator.md
Normal file
121
docs/result-type-operator.md
Normal file
|
@ -0,0 +1,121 @@
|
|||
# `result` type function
|
||||
|
||||
## Summary
|
||||
|
||||
This RFC proposes the addition of a new type function `result`, which can be used to make result types in luau. That are consistent with the idiom established by the [pcall and xpcall global functions](https://luau.org/library#global-functions) in the language currently.
|
||||
|
||||
## Motivation
|
||||
|
||||
Currently, in order to properly type out a result one would have to write the following:
|
||||
|
||||
```luau
|
||||
type Mrow = ((meow: string, mrrp: number) -> (true, string)) &
|
||||
((meow: string, mrrp: number) -> (false, nil))
|
||||
|
||||
--[[
|
||||
Note: the function is being cast to any,
|
||||
as this rfc is being written with the assumption the developer is using --!strict mode
|
||||
--]]
|
||||
local mrow: Mrow = (function(meow: string, mrrp: string)
|
||||
if math.random() > .5 then
|
||||
return true, `{meow} {mrrp}`
|
||||
else
|
||||
return false, nil
|
||||
end
|
||||
end) :: any
|
||||
```
|
||||
|
||||
Due to to that making the developer have to write an overloaded function, and with overloaded functions not consistently working. Most will instead do this:
|
||||
|
||||
```luau
|
||||
type Mrow = (meow: string, mrrp: number) -> (boolean, string?)
|
||||
```
|
||||
|
||||
Leading to having the type burden passed onto the developer using the function, as now they have to cast the result if they want to avoid type errors:
|
||||
|
||||
```luau
|
||||
local success, result = mrow("cat food", ":3")
|
||||
|
||||
if success then
|
||||
local new_result: string = result :: any
|
||||
print(`new food of type: {new_result}!`)
|
||||
else
|
||||
error("no food :(")
|
||||
end
|
||||
```
|
||||
|
||||
Some may take a diffrent approach by making their own result type, where they break from the luau idiom:
|
||||
|
||||
```luau
|
||||
type Result<S, F = nil> = {
|
||||
ok: true,
|
||||
value: S
|
||||
} | {
|
||||
ok: false,
|
||||
value: F
|
||||
}
|
||||
|
||||
local function mrow(meow: string, mrrp: string): Result<string>
|
||||
if math.random() > .5 then
|
||||
return { ok = true, value = `{meow} {mrrp}` }
|
||||
else
|
||||
return { ok = false, value = nil }
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Design
|
||||
|
||||
The functionality of the `result` type function is special, with it being an exception as it'll create a type-pack union. Thus using the result type function will not require the developer to write an overloaded function type.
|
||||
|
||||
```luau
|
||||
type result<S..., F...>
|
||||
```
|
||||
|
||||
```luau
|
||||
local function mrow(meow: string, mrrp: string): result<string>
|
||||
if math.random() > .5 then
|
||||
return true, `{meow} {mrrp}` -- wont error
|
||||
|
||||
return true, nil -- Error message: type 'nil' is not of type 'string'
|
||||
else
|
||||
return false, nil
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Drawbacks
|
||||
|
||||
This type function will need to be special cased, complicating maintenance for the type solver. But, having a result type would allow for pcall and xpcall to get proper types in the future. Where calls to `error` within a function being pcalled would set the second typepack in the result type to the type of the value `error` was called with.
|
||||
|
||||
```luau
|
||||
local function mrow(meow: string, mrrp: string): string
|
||||
if math.random() > .5 then
|
||||
return `{meow} {mrrp}`
|
||||
else
|
||||
error("no cats allowed")
|
||||
end
|
||||
end
|
||||
|
||||
-- inferred as result<string, string>
|
||||
local success, result = pcall(mrow, "cat food", ":3")
|
||||
```
|
||||
|
||||
## Alternatives
|
||||
|
||||
Allow for type pack unions to be written by developers, with the syntax probably looking like this:
|
||||
|
||||
```luau
|
||||
local function mrow(meow: string, mrrp: string): (true, string) | (false, nil)
|
||||
-- code here
|
||||
end
|
||||
```
|
||||
|
||||
With this example breaking backwards compadibility with some types developers may have written already, as today the following is allowed:
|
||||
|
||||
```luau
|
||||
-- inferred as: ((meow: string, mrrp: string) -> (true, string)) | false
|
||||
type mrrp = (meow: string, mrrp: string) -> (true, string) | false
|
||||
```
|
||||
|
||||
Do nothing, and leave it up to developers if they want to write overloaded functions, or make their own result type.
|
Loading…
Add table
Reference in a new issue