Search code examples
scalaimplicitdefault-parameters

Do default parameter values always trump implicits in Scala?


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?


Solution

  • 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.