调用保存在地图中的函数

时间:2014-09-01 06:30:45

标签: scala collections map

我正在阅读Scala School。根据指南,Map可以包含

等功能
def adder(x: Int, y:Int): Int = x + y
def add2(x:Int):Int = adder(2, x:Int)
val add3 = adder(3, _:Int)

val map = Map(
  "adder" -> { adder(_, _) },
  "add2" -> { add2(_) },
  "add3" -> { add3(_) }
)


好。上面的代码是编译的。但是如何调用地图中保存的功能?这些代码不起作用

map.get("adder")(2, 3) // compile error
val adderFunc: (Int, Int) => Int = map.get("adder") // compile error

Scala编译器提供此错误消息

[error] /home/user/scalaExample/src/test/scala/CollectionBasicsTest.scala:61: Option[Object] does not take parameters
[error]     map.get("adder")(2, 3) // compile error
[error]                     ^
[error] /home/user/scalaExample/src/test/scala/CollectionBasicsTest.scala:62: type mismatch;
[error]  found   : Option[Object]
[error]  required: (Int, Int) => Int
[error]  val adderFunc: (Int, Int) => Int = map.get("adder") // compile error

2 个答案:

答案 0 :(得分:5)

这里有两个问题。一个是get返回Option。您可以使用map("adder")来取回功能。

第二个也是最基本的问题是你在地图中放了两个完全不同的东西:一个带有两个参数的函数和一个带有一个参数的函数。这些类型完全不同,这意味着为地图值推断的类型为AnyRef。所以,一旦你找回这样的对象,你就无法对它做任何事情,然后再把它变回一些有用的类型。

只保留地图中具有相同参数数量的函数,并使用第一个提示,事情就可以了。

答案 1 :(得分:2)

尝试:

map("adder")(2, 3)

.get返回Option而非map内的值

<强>更新

正如@EndeNeu所指出的那样,scala的类型推断将地图的类型推断为Map[String, ScalaObject],因为你试图将不同arity的函数放入地图中。

因此,要使上面的示例工作,您必须将可以推广到(Int, Int) => Int的函数放入地图中。

即。有你的例子:

def adder(x: Int, y:Int): Int = x + y
def add2(x:Int):Int = adder(2, x:Int)
val add3 = adder(3, _:Int)

......你可以拥有:

val map = Map(
  "adder" -> { adder(_, _) },
  "another adder" -> { adder(_, _) }
)

map("adder")(2, 3)

......或者这个:

val map = Map(
  "add2" -> { add2(_) },
  "add3" -> { add3(_) }
)

map("add2")(2)

...但是如果你想将所有的加法器存储在同一个地图中,你必须将它们概括为通用类型,可以按照你的预期调用(带有一个或两个参数?)或者将它们转换为它们在运行时使用反射(但这不是类型安全的,并且似乎不适合这种情况)这样:

val map = Map(
  "adder" -> { adder(_, _) },
  "add2" -> { add2(_) },
  "add3" -> { add3(_) }
)

map("adder").asInstanceOf[(Int, Int) => Int](2, 3)