过载中匿名函数的Scala参数类型

时间:2017-02-01 20:35:55

标签: scala anonymous-function overloading

在SO上有关于此错误消息的问题很多,但似乎没有关于此问题。

The argument types of an anonymous function must be fully known. (SLS 8.5)

令人讨厌的代码块试图模仿Ruby的块功能,并且附加的好处是参数可以在过程中进行模式匹配。

object Block {
  def apply(f: => Unit) = apply((_: String) => f)
  def apply(f: String => Unit) = ???
}
def example() = {
  Block { // Error!
    case "A" => println("First letter of the alphabet")
    case _   => println("Not the first letter of the alphabet")
  }
}

即使一行下来,Scala可以清楚地看到我与字符串匹配,但它无法推断出参数类型。

2 个答案:

答案 0 :(得分:1)

这里的问题是有两种apply方法。如果只有一个:

object Block {
  def apply(f: String => Bool) = ???
}

然后一切都会正常工作,因为Scala会看到应用程序并立即了解匿名函数所需的类型。但是,当有两种或更多种不同的方法时:

object Block {
  def apply(f: => Bool) = apply((_: String) => f)
  def apply(f: String => Bool) = ???
}

Scala不能从apply的应用程序中推断出参数的类型,并且它不能从参数的类型中推断出apply的哪个应用程序使用,因此它会被循环捕获。最简单的解决方案似乎是简单地重命名其中一种方法。

object Block {
  def apply(f: => Unit) = apply((_: String) => f)
  def branchOff(f: String => Unit) = ???
}

现在打电话并不困难。

Block { println("This is a regular application.") }
Block.branchOff {
  case "A" => println("A is for aardvark")
  case "B" => println("B is for beaver")
  case _   => println("Huh?")
}

并且您根本不需要指定任何类型参数或任何明确的参数。

关于GitHub的一个帖子中的更多细节:https://github.com/ReactiveX/RxScala/issues/160

答案 1 :(得分:1)

如果您真的喜欢使用两种不同的apply()方法,那么您必须为推理引擎提供一些帮助。

def example() = {
  Block{s:String => s match {
    case "A" => println("First letter of the alphabet")
    case _   => println("Not the first letter of the alphabet")
  }}
}