2.4 KiB
Trailing comma support in calls and function definitions
Summary
Luau will support trailing commas in the following places:
local function definition(
x: number, -- <-- Here, previously a syntax error
)
call(
a,
b, -- <-- Here, previously a syntax error
)
type Fn = (
x: number,
) -> ()
Motivation
Currently, trailing commas are supported in several places in Luau.
local t = {
a,
b,
c,
}
-- Which even means...
f {
a,
b,
c,
}
type Type = {
a: number,
b: number,
}
However, they are not supported in function definitions, types, or calls. This is an unintuitive syntax error and it is obvious what the user intended to do.
Design
We will make these adjustments to the grammar:
funcargs =
- '(' [explist] ')'
+ '(' {exp ','} [','] ')'
| tableconstructor
| STRING
This allows f(a, b, c,)
.
There is no difference between f(a(),)
and f(a())
. Meaning, if a()
returns 1, 2, 3
, then f(a(),)
will be equivalent to f(1, 2, 3)
. This is consistent with tables and { a(), }
.
parlist =
- bindinglist [',' '...']
+ (bindinglist [',' | ',' '...']
| '...' [':' (Type | GenericTypePack)]
This results in:
function f(
a,
b, -- New!
) end
function f(
a,
... -- The usual
) end
function f(
a,
..., -- NOT allowed
)
Trailing comma is not allowed after ...
as it is never correct to put more arguments after the ellipsis. This is consistent with:
- JavaScript supports
function f(a, b,)
, butfunction f(...a,) {}
results in "Rest parameter must be last formal parameter". - Rust supports
Struct { a, ..Default::default() }
, but notStruct { a, ..Default::default(), }
Though this is not universally agreed upon:
- Rust's unstable C variadics support
unsafe extern "C" fn f(a: u32, ...,) {}
, though this syntax is not finalized. - PHP supports
function f($a, ...$args,) {}
- Go requires a trailing comma after every argument, including variadics, if split over multiple lines.
BoundTypeList =
[NAME ':'] Type
[',' BoundTypeList]
+ [',']
| '...' Type
This results in:
type Fn = (x: T,) -> () -- Allowed, new!
type Fn = (x: T, ...U) -> () -- Allowed
type Fn = (x: T, ...U,) -> () -- Not allowed
Drawbacks
There are no interesting drawbacks.
Alternatives
Supporting function f(...,)
is easily doable if the rules seems unintuitive.