14

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

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)

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

谢谢!

4

2 回答 2

30

当你写道:

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

你想让它的意思是:

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

但是,如果您仔细查看错误消息,您会发现编译器并没有这样看,它会将其解析为:

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

如您所见, _ 的范围比您想要的更严格。

_ 总是选择最紧凑的非退化范围。在解析过程中,范围纯粹是在语法上确定的,而不考虑类型。

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

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

最紧的非退化作用域是指由最里面的函数括号相对于下划线定义的作用域。如果没有这样的规则,编译器将无法知道嵌套函数调用时哪个 _ 对应于哪个函数。

于 2011-03-10T13:00:44.727 回答
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))

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

详细说明在第 8.5 章。“Scala 编程”一书中的占位符语法

于 2011-03-10T12:25:52.607 回答