为什么 scala 无法推断映射的 NodeSeq 的类型?

Why is scala failing to infer the type of mapped NodeSeq?

我正在尝试从一组 xml 元素的 id 属性中提取 ID,但失败并出现类型错误:

scala> (xml \ "contentitem").map( (_ \ "@id").text )
<console>:14: error: missing parameter type for expanded function ((x) => x.$bslash("@id"))
       (xml \ "contentitem").map( (_ \ "@id").text )
                                    ^

当我在我的地图中明确提供一个命名的 val (elem) 时,它起作用了:

scala> (xml \ "contentitem").map( elem => (elem \ "@id").text )
res8: scala.collection.immutable.Seq[String] = List(20761, 22798, 22799, 21167, 21438, 20770, 21480, 21906, 21907, 21923, 22766, 22771, 22794, 22800, 22803, 22804, 22818, 22819, 22820, 22821)

我不明白这里的区别。 elem_ 有何不同?

当你这样写的时候:

list map(_.toInt)

你直接告诉编译器你想映射list的元素。当你写:

(xml \ "contentitem").map( elem => (elem \ "@id").text )

你告诉编译器你想获取elem并映射它,这和我前面的例子一样,但更明确。然而,当你写:

(xml \ "contentitem").map( (_ \ "@id").text )

您没有告诉它您想要隐式(我的第一个示例)或显式(您的第二个示例)使用集合的元素。相反,你告诉它取任何东西 _ 并提取 id。

TLDR;它不会无法推断出类型。你没有告诉编译器你想要什么。

Scala 正在寻找在将占位符语法转换为匿名函数时形成 "complete" 表达式的最内部部分。不让我们看看你的例子:

(_ \ "@id").text

其实里面还有一个完整的表达式:

_ \ "@id"

所以这个表达式被转换为匿名函数:

x => x \ "@id"

然后在外部表达式中用作:

(x => x \ "@id").text

现在在这个表达式中没有办法推断 x 的类型,因此你的错误信息是:

missing parameter type for expanded function ((x) => x.$bslash("@id"))

更新

_ 本身不被认为是一个完整的表达式,因此代码 .map(List(_)) 有效,因为最内部的完整表达式是 List(_) 并且它将被转换为 x => List(x)

http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#placeholder-syntax-for-anonymous-functions