Say we have:
trait BinaryOperator[A, B, X]:
extension(left: A)
apply(right: B): X
With an implementation of:
object + extends BinaryOperator[Double, Double, Double]:
extension(left: Double)
override def apply(right: Double): Double = left + right
At present, the only thing this does is allow us to write
import +.apply
val three = 1 apply 2
or
import +
val three = +(1)(2)
I find apply
methods very powerful, because they let instance names become method names and can make code far cleaner. I find extension methods very powerful because they provide a way to bundle potentially very complex functionality in a way that can make it very easy to apply or extend. A great example is the whole family of methods you can get from things like extension[T: Foo](target: T)
.
Unfortunately, these two great language features have no real interaction with each other, at least that I know of.
I can think of two intuitive ways that apply
could be interpreted in the context of extension methods:
- Extension methods named
apply
make the containing instance itself usable as an extension method. Using my example above, this would allow:
import +; val three = 1 + 2
(and let’s just imagine that we don’t already have+
forDouble
s )
This would be pretty consistent with the existing interpretation of general methods namedapply
- essentially letting us move from+(1)(2)
to1.+(2)
thanks to theextension
declaration. - Extension methods named
apply
act as if they were methods namedapply
defined on the target class. This would translate to:
import +.apply; val three = 1(2)
A little more nonsensical in this specific example, but still something that would be useful in other cases.
First prize would be having access to both features using different keywords, but either of these would be a great features to have, and I think it would be a waste to leave the non-interaction between extension
and apply
the way that it is.
EDIT: @Sporarum has pointed out that number 2 is already available in the language - my bad!