Search code examples
scalascala-placeholder-syntax

Underscore in Named Arguments


Can someone explain me what exactly is going on here? I am not fully getting into it right now:

val s = Seq(1D,2D,3D,4D)
case class WithUnit(value: Double, unit: String)
s map { WithUnit(_,"cm") } // works
s map { WithUnit(value = _ , unit = "cm") } // error: missing parameter type for expanded function ((x$2) => value = x$2)

I guess the compiler can´t infer the parameter type because I wrote the name of the argument. But why not? It shouldn´t be more difficult only because of stating the name of the argument?!

Thanks!


Solution

  • When you wrote:

     WithUnit(value = _, unit = "cm")
    

    You wanted it to mean:

     x => WithUnit(value = x, unit = "cm")
    

    But if you take a close look at the error message, you'll see that the compiler didn't see it that way, it parsed it as:

     WithUnit(x => value = x, unit = "cm"})
    

    As you can see, the _ is scoped more tightly than you wanted.

    _ always picks the tightest non-degenerate scope it can. The scope is determined purely syntactically, during parsing, without regard to types.

    By non-degenerate, I mean that the compiler didn't think you meant:

    WithUnit(value = x => x, unit = "cm")
    

    Tightest non-degenerate scope means the scope defined by the innermost function parenthesis relative to the underscore. Without such a rule the compiler wouldn't be able to know which _ corresponds to which function when function calls are nested.