可以给个{key->;的地图吗? Scala 中的函数调用}?
我正在尝试创建一个具有键映射的类 ->函数调用,并且以下代码的行为不符合我的预期。
class MyClass {
val rnd = scala.util.Random
def method1():Double = {
rnd.nextDouble
}
def method2():Double = {
rnd.nextDouble
}
def method3():Double = {
rnd.nextDouble
}
def method4():Double = {
rnd.nextDouble
}
def method5():Double = {
rnd.nextDouble
}
var m = Map[String,Double]()
m += {"key1"-> method1}
m += {"key2"-> method2}
m += {"key3"-> method3}
m += {"key4"-> method4}
m += {"key5"-> method5}
def computeValues(keyList:List[String]):Map[String,Double] = {
var map = Map[String,Double]()
keyList.foreach(factor => {
val value = m(factor)
map += {factor -> value}
})
map
}
}
object Test {
def main(args : Array[String]) {
val b = new MyClass
for(i<-0 until 3) {
val computedValues = b.computeValues(List("key1","key4"))
computedValues.foreach(element => println(element._2))
}
}
}
以下输出
0.022303440910331762
0.8557634244639081
0.022303440910331762
0.8557634244639081
0.022303440910331762
0.8557634244639081
表明,一旦将函数放置在映射中,它就是一个冻结实例(每个键为每次传递生成相同的值)。我希望看到的行为是键引用函数调用,生成新的随机值,而不是仅返回映射中保存的实例。
I'm trying to create a class that has a map of keys -> function calls, and the following code is not behaving as I would like it to.
class MyClass {
val rnd = scala.util.Random
def method1():Double = {
rnd.nextDouble
}
def method2():Double = {
rnd.nextDouble
}
def method3():Double = {
rnd.nextDouble
}
def method4():Double = {
rnd.nextDouble
}
def method5():Double = {
rnd.nextDouble
}
var m = Map[String,Double]()
m += {"key1"-> method1}
m += {"key2"-> method2}
m += {"key3"-> method3}
m += {"key4"-> method4}
m += {"key5"-> method5}
def computeValues(keyList:List[String]):Map[String,Double] = {
var map = Map[String,Double]()
keyList.foreach(factor => {
val value = m(factor)
map += {factor -> value}
})
map
}
}
object Test {
def main(args : Array[String]) {
val b = new MyClass
for(i<-0 until 3) {
val computedValues = b.computeValues(List("key1","key4"))
computedValues.foreach(element => println(element._2))
}
}
}
The following output
0.022303440910331762
0.8557634244639081
0.022303440910331762
0.8557634244639081
0.022303440910331762
0.8557634244639081
indicates that once the function is placed in the map, it's a frozen instance (each key producing the same value for each pass). The behavior I would like to see is that the key would refer to a function call, generating a new random value rather than just returning the instance held in the map.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题出在您的地图
m
的签名上。您描述了您想要将功能放入地图中;但是您已将其声明为 Map[String, Double] ,它只是字符串到双精度数的映射。正确的类型是 Map[String, () =>双]。由于括号在无参数方法调用中是可选的,因此这里类型的差异非常重要。填充映射时,会在插入时调用这些方法以匹配类型签名(我相信这是通过隐式转换完成的,但我不能 100% 确定)。
只需更改映射的声明签名,即可根据需要插入函数,并且可以在computeValues期间进行评估(需要将第35行更改为map += {factor -> value()}),产生以下输出(在 Scala 2.8 上测试):
The problem is with the signature of your map
m
. You described that you wanted to put functions in the map; however you've declared it asMap[String, Double]
which is just a map of strings to doubles. The correct type would beMap[String, () => Double]
.Because brackets are optional on no-arg method invocations, the difference in types here is very important. When the map is being populated, the methods are invoked at insertion time in order to match the type signature (I believe this is done by an implicit conversion but I'm not 100% sure).
By simply changing the declared signature of your map, the functions are inserted as you desire, and can be evaluated during
computeValues
(requires a change on line 35 tomap += {factor -> value()}
), resulting in the following output (tested on Scala 2.8):您需要将按键映射到函数,而不是映射到函数给出的答案。试试这个:
You need to map the keys to functions, not to the answer that the function would give you. Try this:
我会使用 scala 的类型推断来定义映射。
如果仅通过地图使用这些方法,则无需单独定义这些方法。
您还可以使用不可变的 val,而不是可变的 var。
您还需要将第 35 行更改为 value()
I would use scala's type inference to define the map.
There's no need to define the methods separately, if they're only used via the map.
Also you can use an immutable val, instead of a mutable var.
You also need to change line 35 to value()