命名参数中的下划线

时间:2011-03-10 11:24:41

标签: scala

有人能解释一下这到底发生了什么吗?我现在还没有完全了解它:

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)

我猜编译器无法推断参数类型,因为我写了参数的名称。但为什么不呢?仅仅因为陈述参数的名称应该更难吗?!

谢谢!

2 个答案:

答案 0 :(得分:29)

当你写道:

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

你希望它意味着:

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

但如果仔细查看错误消息,您会看到编译器没有看到它,它将其解析为:

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

正如您所看到的,_的范围比您想要的更紧密。

_总是选择最紧密的非退化范围。范围在语法分析期间纯粹由语法决定,而不考虑类型。

非退化,我的意思是编译器没有认为你的意思:

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

最严格的非简并范围是指最内层函数括号相对于下划线定义的范围。没有这样的规则,当嵌套函数调用时,编译器将无法知道哪个_对应于哪个函数。

答案 1 :(得分:3)

试试这个:

scala> val withUnits = s map { x => WithUnit(value = x, unit = "cm") }
withUnits: Seq[WithUnit] = List(WithUnit(1.0,cm), WithUnit(2.0,cm), WithUnit(3.0,cm), WithUnit(4.0,cm))

问题是使用下划线直接定义任何一个函数。

详细说明见chapter 8.5. Placeholder syntax in the "Programming in Scala" book