local a = 2
-- would this
foo((a)=>a+1,a+2)
-- be equivalent to
foo(function(a)return a+1,a+2 end)
-- or
foo(function(a)return a+1 end,a+2)
This syntax would also complicate parsing
Example
local a,b,c
-- ...
foo((a:typeof(b))=>a)
-- ^
-- to figure out the meaning of the second opening parenthesis
foo((a:typeof(b))=>a)
-- ^
-- the name could be a parameter name or variable which is used
foo((a:typeof(b))=>a)
-- ^
-- the colon could be giving a type to the parameter or it could be a method call
foo((a:typeof(b))=>a)
-- ^^^^^^
-- could be the name of a method or typeof in a type context
foo((a:typeof(b))=>a)
-- ^
-- could be a method call or calling typeof in a type context
foo((a:typeof(b))=>a)
-- ^
-- could be a variable passed in or used to get the type from
foo((a:typeof(b))=>a)
-- ^
-- could be ending the method call or typeof call in a type context
foo((a:typeof(b))=>a)
-- ^
-- ends closing parenthesis, but still unclear what the meaning of the parenthesis is
foo((a:typeof(b))=>a)
-- ^^
-- disambiguating token, now the meaning of the parenthesis is known
You should also add use cases for this syntax, when would having this shorthand syntax for functions be useful?
In your first example, it would be equivalent to the second option, you would need to wrap the returns like such to achieve the first option: foo((a)=>(a+1,a+2)).
In your parsing examples list I’m not sure if any of those are valid syntax, the first set of () can only contain argument names, not a:typeof(b) calls… I’m not sure I understand your point there?
I don’t think what is “normal” matters here since I’m suggesting changing the norm and adding new language features…
foo((a)=>(a+1)*2) would be equivalent to foo((a)=>((a+1)*2)). There is no ambiguity there either… You would need to type foo(((a)=>(a+1))*2) out to achieve the second option.
The typed variable api should still work here without changes: testFunc((x: number) => x*20)
The problem is that if the parenthesis are treated specially to allow for multiple values, then there can’t be an operator which acts on the result of the parenthesized expression as there could be multiple values.
foo((a)=>(a,a)*2)
-- in this case it would only make sense to multiply by the function by 2
foo((a)=>(a)*2)
-- so it would be weird for it to be different in this case
foo((a)=>(bar(a))*2)
-- this would be problematic even if there was some special case
-- as bar could return multiple results which wouldn't be so unlike the first case
foo((a)=>(a,a)*2) is invalid syntax, you cant multiply a function by an integer. You’re trying to do foo((function(a) return a, a end)*2), which would error, so it’s still consistent.
It generates an error, but it’s correct syntactically. Not all errors are syntactic. Metamethods could be used to attribute meaning to multiplying a function
local t = setmetatable({},{__mul=function(f)return f end})
local f = function(a)return a,a end*t
print(f"a") --> a a
I’m not sure how this causes inconsistencies unless you just mean it’s unintuitive?
It would error on foo((a)=>(a,a)*2) but not error on foo((a)=>(a,a)*t)
I would be perfectly happy with this approach! I mentioned that I just need JS-like arrow functions, I don’t have very specific preferences for how it works syntactically as long as it’s familiar.
local a = (b) => {b()}
-- is this a function that just calls the first argument
-- or a function that calls the first argument and puts all the results in a table?
local a = (b) => {b();}
-- this also has the same problem
The first example is missing an opening parenthesis? It would also result in an ambiguous syntax because it conflicts with method calling syntax (e.g. ((name:string)=>"hello, "..name):typeof("s") could be interpreted as a method call on the function).
<T> would be confusing for specifying the return type as it looks like it would be a specifying generic types, which it isn’t.
This syntax still has the same problem with complicate parsing when determining if an opening parenthesis is an arrow function or a parenthesized expression.
The inconsistency would be that if the parenthesized expression had a comma in it then it would be treated differently from if it didn’t.
foo((a)=>(a)*t)
-- would become
foo(function(a)return a*t end)
foo((a)=>(a,a)*t)
-- would become
foo(function(a)return a,a end*t)
This feature seems more effort than it is worth, the grammar would be complex to parse, there would have to be weird semantics to make multiple return values work correctly, and the syntax to make it work with types and generic functions would be weird (<T>(v:T):(T,T)=>(v,v)?).
-- Current Syntax
local hello: (string) -> (string) = function (name) return "hello, " .. name end
-- Proposed Syntax
local hello: (string) -> (string) = (name) => "hello, " .. name
Your proposed syntax is currently valid Lua code. You’re suggesting a fundamental change to the language’s semantics at that point.
If we’re going to be serious about this, I would suggest something similiar to Rust’s syntax, which doesn’t have any conflicts with Lua:
local hello: (string) -> (string) = |name| "hello, " .. name
local hello2: (string) -> (string) = |name| { return "general " .. name }
The problem with the latter is that it of course introduces the idea of brackets being equivalent to do blocks, which wouldn’t be the case anywhere else in the language.
Up to the Luau team to consider if they care about that or not, but they probably should.
Sorry, wrote that when I was tired and thought that was >=.
In the same vein, I forgot that functions can return other functions which can then be called with the table syntax. Still would prefer Rust’s syntax over JS/TS, but either way you’d probably have to use something like do for blocks so it’ll be gross regardless.
I may also be in favor of a shorter syntax for anonymous functions as it makes higher order functions a bit cleaner and nicer to look at. Although I can’t think of any other purpose for lambda functions (in javascript there are quite a few reasons to use the arrow function other than shorter syntax). As such, allowing multiple expressions seems unnecessary and disallowing it would make syntax a lot simpler.