我正在阅读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
答案 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)