扩展函数缺少参数类型 - 它依赖于什么?

时间:2015-10-26 08:04:28

标签: scala types

class A {
  def a(): Unit = ()
  def b[T](f: A => T): T = f(new A())
  def c(): Unit = b { _.a() }
  def d(): Boolean = b { w => w.a(); true }
//def e(): Boolean = b { _.a(); true } // does not compile - why not, if c compiles?
}

在上面的类的e()方法中,我认为编译器能够像在c()中一样推断出“_”的类型。但是,对于scala 2.11.7,e()会导致“扩展函数缺少参数类型。为什么?编译器应该能够(=编译器错误)或者编译器在抱怨时是否正确?

2 个答案:

答案 0 :(得分:1)

我认为这是因为b { _.a(); true }由编译器翻译成b { w => { w.a() }; true }而不是预期的b { w => { w.a(); true } }。因此,它计算整个表达式并尝试将Boolean类型的表达式传递给b而不是A => Boolean。至少那是我看到的唯一解释,不幸的是我不知道如何检查。编译器的错误似乎在试图说出这一点时非常诚实。

总的来说,您不应该将_通配符与复杂表达式一起使用。它们仅适用于简单的

我也认为@Felix评论你的问题也是正确的 - 部分问题也是如此。编译器含糊不清:T可以是UnitBoolean,它只是错误地解决了它。不幸的是,即使您定义b接受A => Boolean

,它也无济于事

P.S。通过适当的编译器消息,我的意思是:

Error:(24, 36) type mismatch;
 found   : Boolean(true)
 required: Main.A => Boolean
    def e(): Boolean = bb { _.a(); true } // does not compile - why not, if c compiles?
                               ^

答案 1 :(得分:0)

首先,我不认为它是scala编译器的错误。

对于函数d(),它应该扩展为:

def d(): Boolean = b { w => {w.a(); true} }

def d(): Boolean = b { {w => w.a()}; true } 

所以这可能会引起一些歧义。

用于函数e(),因为编译器不知道指定类型的通配符_

示例:

scala> def f(s: String): String = s
f: (s: String)String

scala> List("foo", "bar").map(f(_.toUpperCase))
<console>:12: error: missing parameter type for expanded function ((x$1) => x$1.toUpperCase)

scala> List("foo", "bar").map(i => f(i.toUpperCase))
res3: List[String] = List(FOO, BAR)

因为对于无穷无尽的函数,编译器无法推断出通配符_的类型。

def e(): Boolean = b { _.a(); true } 

编译器不知道上面代码中_的类型。

因为它可以翻译为:

def e(): Boolean = b {{_.a()}; true } 

或:

def e(): Boolean = b {{x => x.a()}; true }