Some new thoughts on the second issue: what syntax to choose for a direct call to an extension method. To recap: Given
object obj:
extension (x: A) def fun (y: B) = ...
How do I call obj.fun
directly, without using it as an extension method? This matters for two reasons:
- It’s a way to disambiguate things for the programmer if the extension method is not found at all, or the wrong one is found.
- It’s a way for the language definition to describe what an extension method application means.
Elaborate extension method call syntaxes like the ones we have been discussing address only the first aspect. They don’t solve the second, since we still have to explain what those elaborate syntaxes mean.
By contrast, the extension_fun
name mangling provides a solution for both aspects. On the other hand, the extension_
name mangling has problems on its own. When do you use the extension_
name, when the normal one? It’s all a bit arbitrary.
So maybe we can do without extension_
? An alternative rule would simply state that an extension method like fun
above would translate to a method
object obj:
<extension> def fun(x: A)(y: B) = ...
The <extension>
modifier is not accessible to user programs. Such methods can be called like any other methods. So a.fun(b)
would translate to obj.fun(a)(b)
, which is by itself a legal expression.
There are several tricky aspects about this, but I believe they can be solved.
-
We have to make sure that overrides respect extensionality. Only extension methods can override
other extension methods, and all overrides of extension methods must again be extension methods. -
Direct calls to extension methods must be selections with a qualifier and a dot. To see why, consider a collective extension like this one:
object obj: extension (x: A) def fun (y: B) = ... def other = fun(B())
Here, the
fun(B())
call inother
expands tox.fun(B())
. So it cannot be a direct call. To make it a direct call, you’d have to writeobj.fun(a)(B())
. -
This means we cannot call an extension method directly at all if it is locally defined. Take the example above but now in a
def
instead of in anobject
:def outer(a: A, b: B) = extension (x: A) def fun (y: B) = ... a.fun(b) // has no direct equivalent
We cannot call
fun
directly, since there is no prefix from which we could select afun
. This is a hassle primarily for the language definition, where we’ll have to do some handwaving or resort to more awkward notation. For programming I don’t think it will matter, since it is an edge case of an edge case of an edge case. Direct calls of extension methods are already the rare exception. Local extension methods will be also quite rare, even though I see them to be useful on occasion. But if I have a local extension method, I don’t usually need to call it directly, since it is the thing that shadows all other possibilities anyway. So I can’t really see a scenario where one would write a local extension method that needs to be called directly. In that case, one should have defined the method as a normal method in the first place.
If we follow this route, we still have to decide whether extension
should be a hard or a soft keyword. I am sitting on the fence here. On the one hand, making it a hard keyword is cleaner since it makes every word that can start a definition a hard keyword. On the other hand this will cause considerably breakage (starting with all code that calls extension
on a file or a path). So, not sure about this one.