No, foo(x: int) is not a string, it's not even an expression, it's not even an AST node. It's a fragment of the larger ast node
fn foo(x: int) -> ReturnType {
body
}
The ast here splits into
Function {
name: foo
signature: (x: int) -> ReturnType
body: body
}
I.e. the arrow binary op binds more tightly than the adjacency between foo and x: int. And the type of foo is a function, not a string.
A "better" way to write this (in that it breaks down the syntax into the order it is best understood) might be
static foo: (Int -> ReturnType) = {
let x = arg0;
body
}
Or to put it another way. Reading foo(x: int) as "foo applied to x" in this case is a mistake, because that's now how things bind. You should read that "foo is a (function that takes Int to String)". It's a syntactic coincidence that foo and x are beside eachother, nothing more.
Ya, I'm not really going to defend the current syntax past "function syntax is hard".
It's mixing up assigning a global variable, specifying that variables type, and destructuring an argument list into individual arguments, in one line. I've played at making my own language, and this is one part that I've never been satisfied with.
Personally I'd probably at least go with a `foo = <anonymous function>` syntax to split out the assigning part. But that's spending "strangeness budget" because that's not how C/Python/Java do it, and I can understand the decision to not spend that budget here...
A "better" way to write this (in that it breaks down the syntax into the order it is best understood) might be
Or to put it another way. Reading foo(x: int) as "foo applied to x" in this case is a mistake, because that's now how things bind. You should read that "foo is a (function that takes Int to String)". It's a syntactic coincidence that foo and x are beside eachother, nothing more.