Type parameter syntax when defining vs. calling functions


#1

When defining a generic function, the type parameter syntax looks like this:

fn generic<T, ...>(...) ...

But when calling it, there’s an additional double-colon between the function name and the pointy brackets:

generic::<T, ...>(...)

Would anyone happen to know if there’s a particular reason for this? I must admit it had me confused for quite a while, the calls looked a bit like magic to me since you don’t see this syntax (::<...>) elsewhere and I didn’t immediately make the connection with generic function definitions :slight_smile:

To be entirely clear on what I’m trying to get at: if the syntax for the definition and the call had been the same, I think it would have been clear to me they’re one and the same thing from the get go. So I’m wondering if there’s a particular reason why they’re not :slight_smile:


#2

I suspect it is a way to resolve a syntaxic ambiguity in the language grammar. Without the double colon, the beginning of the generic function call syntax would look like a call to the “<” comparison operator.


#3

Right, that makes sense, it must have been the reason at some point! Though currently, the parser seems to be smarter, because

let foo = 1;
let bar = 2;
foo<bar>(foo);

errors out with error: chained comparison operators require parentheses (and a suggestion to use the double-colon if what the user actually meant was specifying type parameters).

I guess it could have also gone the other way, with the double-colon being added to the definition as well, but type annotations in function definitions can get heavy as it is, so the syntax is trying to provide ways of reducing the clutter (where clauses) rather than adding more. So that part makes sense as well :slight_smile:

In any case, thanks!


#4

BTW, the ::<..> syntax is called turbofish.