2012-10-04 55 views
3

我不明白为什么斯卡拉需要我有时命名参数传递给匿名FNS:为什么scala有时需要在匿名函数中命名的参数?

scala> case class Person(name: String) 
defined class Person 

scala> def reverseString(s: String) = s.reverse 
reverseString: (s: String)String 

scala> val p = Some(Person("foo")) 
p: Some[Person] = Some(Person(foo)) 

scala> p map { reverseString(_.name) } 
<console>:12: error: missing parameter type for expanded function ((x$1) => x$1.name) 
       p map { reverseString(_.name) } 

// why does it only work when I name the argument? I'm not even telling it the type. 
scala> p map { p => reverseString(p.name) } 
res9: Option[String] = Some(oof) 

// and shouldn't this fail too? 
scala> p map { _.name.reverse } 
res13: Option[String] = Some(oof) 
+0

可能重复[管理下划线以定义匿名函数的规则是什么?](http://stackoverflow.com/questions/28125850/what-are-the-rules-to-govern-underscore-to-define-anonymous-function) – Suma

回答

4

答案是错误消息,但含糊这样:

(x$1) => x$1.name 

等一下,什么?你想要x$1 => reverseString(x$1.name)

所以,现在你看看到底出了什么问题:它承担的功能是reverseString括号(即你想给一个函数传递给reverseString)。通过明确命名变量,你向它证明它是错误的。

(因为一旦它假定reverseString应传递一个函数,它不知道做的是功能是什么类型,因为reverseString其实想要一个字符串,而不是一个功能它提供了该消息。)的

+0

那么为什么它不是首先扩展到'x $ 1 => reverseString(x $ 1.name)?在这个例子中:'val double =(x:Int)=> x * 2; val doubled = 1到5 map {double(_)}'不会'_'扩展为'(Int => Int)'并且失败,因为'double'需要'Int'? – devth

+1

@devth - 不,因为单独作为参数意味着“部分应用”(即,从该方法中创建一个函数,将任何未应用的参数作为参数),并且部分应用的函数(包含整个参数列表)为只是这个功能。做更复杂的事情,比如'double(_ * 2)',它会因为同样的原因而失败。 –

+0

啊,这很有道理。所以关于我的另一个问题 - 为什么Scala没有扩展到更明智的'x $ 1 => reverseString(x $ 2.name)'?有没有这种情况,这将是一个不好的假设? – devth

0

我相信这是什么类型推断称。另外,_只是一个占位符。 (您已经定义数p作为类型某些[人]这样用你的方式时,编译器是足够聪明,明白这一点)

相关问题