def foo(implicit i: Int = 1) = i
def bar(implicit j: Int) = foo()
bar(4)
This piece of code evaluates to 1
. So the default value has priority over the implicit j
, which is instantiated to 4
. Therefore, it seems that, at least in this example, the default parameter value trumps implicit
, making the definition of foo
equivalent to def foo(i: Int = 1) = i
.
Do default parameter values always trump implicits? If yes, why is this code legal (given that it is confusing)? If not, what is a counter-example?
Is there a way to get the other behavior, i.e. that a piece of code similar to the above (with a default value for i
) would evaluate to 4
, without having to pass the argument explicitly?
implicit
is applied to the entire parameter list, not just a single parameter (e.g., you can have foo(implicit i: Int, j: Int)
, and both parameters are implicit, but, if you wanted only one of them to be, you'd have to split them in two lists: def foo(i: Int)(implicit j: Int)
.
So, to pass implicit parameters to the function, you have to omit the entire list: foo
, not foo()
.
When you have def foo(implicit i: Int)
, foo()
does not even compile, because you are trying to send an empty parameter to list. foo
does (as long as an implicit int is in scope), because the list is passed implicitly.
With def foo(implicit i: Int = 1)
, both uses compile, but mean different things. foo()
means "call foo
with default values for all parameters", foo
means "call foo
, passing the implicit parameter list".
So, with bar(implicit j: Int) = foo
it will evaluate to the value of j
, while bar(implicit j: Int) = foo()
evaluates to 1.