luau/rfcs/arrow-functions.md
2023-09-09 13:55:07 +03:00

99 lines
2.6 KiB
Markdown

# Arrow functions
## Summary
Reduce boilerplate and improve readability by introducing an arrow function syntax
## Motivation
Luau is a very flexible language where functions are often used as values. Many libraries use that extensively:
- [roblox-lua-promise](https://github.com/evaera/roblox-lua-promise)
- [Fusion](https://github.com/dphfox/Fusion)
Unfortunately, heavy usage of functions as values leads to a lot of unnecessary boilerplate:
```lua
Promise.new(function(resolve)
somethingThatYields()
resolve(1)
end)
:andThen(function(x)
return Promise.new(function(resolve)
somethingThatYields()
resolve(x + 1)
end)
end)
:andThen(print) --> 2
```
## Design
This RFC proposes the addition of the arrow function syntax, which exists in many languages such as [javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), [C#](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-operator), etc.
The syntax goes as follows:
```lua
(...) => expression
(...) =>
statements
end
```
The only difference is the syntax. Under the hood these still evaluate to regular functions:
```lua
function(...)
return expression
end
```
For single expression arrow functions, you don't need the `end` keyword. They also return the expression:
```lua
local myArrowFunc = (n) => n * 2
print(myArrowFunc(3)) -- 6
```
Adding multiple expressions or statements should cause an error. When you want your arrow function to do more, you can insert the `end` keyword. This effectively makes it so that the body of the arrow function is treated as a regular function:
```lua
local myOtherArrowFunc = (n) =>
n *= 2
n -= 1
return n
end
print(myOtherArrowFunc(5)) -- 9
```
### Preview of the arrow function in real use cases
Promises
```lua
Promise.new((resolve) =>
somethingThatYields()
resolve(1)
end)
:andThen((x) => Promise.new((resolve) =>
somethingThatYields()
resolve(x + 1)
end)
end)
:andThen(print) --> 2
```
Fusion
```lua
local text = Value("hello")
local upperText = Computed((use) => use(text):upper())
New "TextButton" {
Text = upperText,
[OnEvent "Activated"] = () =>
print(":)")
print(peek(upperText))
end
}
```
## Drawbacks
I'm not aware of any drawbacks other than slightly increasing the complexity of the language. The current proposed syntax is invalid, so it should be fully backwards compatible.
## Alternatives
Instead of `=>`, `->` could be used. Personally I'm not a big fan of that because `->` overlaps with the function type syntax. Arrow functions could potentially also work without the arrow, but I reckon it would be a nightmare to parse.