I agree the default argument syntax is attractive because it is familiar. The problem is, it leads to a completely different system of implicits than what we have now.
In particular implicit parameters are tied to normal applications. For instance, we currently have a max
extension method on lists, which is roughly defined like this:
class ListOps[T](xs: List[T]) {
def max(implicit ord: Ordering[T]) = ...
}
You call it like this: List(1, 2, 3).max
.
With the implicit as default params proposal that would now do something different. It would expand to (ev: Ordering[Int]) => List(1, 2, 3).max(ev)
, i.e. it would return a function that takes an ordering and produces a number. You have to pass a ()
argument to max
to get the maximum: List(1, 2, 3).max()
. That’s just how default arguments work: They fill in missing arguments inside an argument list but if the (...)
is missing you get an eta expansion instead.
The example also shows something more fundamental: Current implicits and implicits-as-defaults behave differently under partial application. Given
def max[T](x: T, y: T, ord: Ord[T] = implicit): T = ...
What would max[Int]
without further arguments expand to? According to the rules for default parameters it would be:
(x, y, ord) => max[Int](x, y, ord)
But according to current (both old and new-style) implicits it would be:
(x, y) => max[Int](x, y)(IntOrdering)
See the difference? The implicit argument moved from definition to use site! This makes implicits a whole lot more like dynamic scoping. Maybe that would work and maybe it wouldn’t. But it sure is completely different to what we have now! And, I believe it’s fair to say that the behavior of implicits under partial applications works fine as is, at least I can’t recall anybody complaining about it.
One could consider tweaking the rules so that default arguments with implicits behave somehow different from normal default arguments so that we can get back the status quo. But that would be a classical “easy instead of simple” move. We buy the easy familar syntax at the price of complex rules that mix things like implicits, default arguments and partial application that formerly were better separated. So, that’s why, much as I like the syntax. I don’t think implicits as defaults are the right way to go.