【问题标题】:Scala - Confusion with lambda in map functionScala - 地图函数中的 lambda 混淆
【发布时间】:2016-07-27 22:34:45
【问题描述】:

我正在学习 Scala 并在命令行中进行试验。我无法理解为什么第二行无法编译。谁能解释一下。

val list = List(1,2,3,4)
list.map(_+1)           //This works. List(2,3,4,5)
list.map(List(_+1))     //But, Compilation Fails here
list.map(x=>List(x+1))  //This works. List(List(2),List(3),List(4),List(5))

谢谢。

【问题讨论】:

标签: scala lambda


【解决方案1】:

Scala 会将_(在占位符位置使用时)扩展为x => x,除非这种扩展会导致标识函数(本答案末尾的更多信息):

list.map(_+1)       // same as list.map(x => x + 1)       (1)
list.map(List(_+1)) // same as list.map(List(x => x+1))   (2)

(1) 的情况下,scala 可以推断出x 的类型为Int(因为list: List[Int])。
但是(2) 失败了

error: missing parameter type for expanded function ((x$1) => x$1.$plus(1))

因为 scala 无法推断 xList(x => x+1) 中的类型。


关于扩展和标识函数:

scala> list.map(List(_))
res3: List[List[Int]] = List(List(1), List(2), List(3), List(4))

有效,因为list.map(List(x => x)) 扩展被拒绝,下一个可能的扩展是list.map(x => List(x)),它给出res3

【讨论】:

  • 呸,打败我。
  • "Scala 会将_ 扩展为x => x,除非这种扩展会产生恒等函数"。这个说法是不是有问题? x => x 是身份函数。
  • @VictorMoroz:啊,是的,我可能不得不重新措辞。我的意思是:将f(_) 扩展到f(x => x) 将用身份函数替换_。用f(x => x + 1) 扩展f(_ + 1) 不会。
  • 我的理解是,_ 单独是永远不会被标识函数取代的,检查这个:List(1).map(_)。我不太确定它在语言规范中的声明位置。
【解决方案2】:

list 的类型是List[Int]。所以,list.map(...) 的参数必须是从Int 到某个东西的函数。

您似乎试图用List(_+1) 创建的是一个从整数到恰好有一个元素的整数的函数列表:后继函数。

它无法编译,因为这是 Scala 编译器无法推断表达式类型的情况之一。但实际上,List[_] Int 到某事的有效函数:

val f = List(99, 88, 77)
f(1)                     // -> 88

所以要编译你的代码,你必须给编译器一点提示,以便它进行类型检查:

val list = List(1, 2, 3, 4)
list.map(List[Function[Int, Int]](_ + 1))
//           ^^^^^^^^^^^^^^^^^^^^ type annotation

这也是有效的:

list.map(List[Int => Int]](_ + 1))

它会编译,但在运行时会失败,因为您正在尝试获取单元素列表的元素 1、2、3 和 4。如果列表只包含零(该特定列表的唯一有效索引),它会起作用:

val list = List(0, 0, 0)
list.map(List[Function[Int, Int]](_ + 1))
// -> evaluates to a list of three functions 

...或者如果函数列表包含足够的元素以使索引 1、2、3 和 4 存在:

val list = List(1, 2, 3, 4)
list.map(List[Function[Int, Int]]( // a list of 5 functions:
  _ + 1,                           // 0) the successor function,
  _ * 10,                          // 1) the "append a zero" function,
  Math.abs,                        // 2) the absolute value function,
  _ / 2,                           // 3) the half function
  x => 2                           // 4) the constant function with value 2
))
// -> evaluates to a list of four functions. Can you guess which ones?

【讨论】:

  • list.map(List((_:Int) + 1))) 可以说比list.map(List[Function[Int, Int]](_ + 1))简单
猜你喜欢
  • 2013-03-26
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 1970-01-01
相关资源
最近更新 更多