在命名参数中下划线

有人能解释一下这里究竟发生了什么吗? 我现在还没有完全搞清楚:

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) 

我猜编译器不能推断参数types,因为我写了参数的名字。 但为什么不呢? 仅仅因为陈述论点的名字就不应该更困难了!

谢谢!

当你写道:

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

你想这意味着:

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

但是,如果仔细查看错误消息,您会看到编译器没有这样看,它parsing为:

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

正如你所看到的,_的范围比你想要的要紧得多。

总是select最紧密的非简并范围。 范围是纯粹的语法确定,在parsing时,不考虑types。

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

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

最简单的非退化范围意味着由最内层函数括号定义的范围相对于下划线。 没有这样的规则,当函数调用被嵌套时,编译器将无法知道哪个_对应于哪个函数。

尝试这个:

 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章。 “Programming in Scala”书中的占位符语法 。