是否有可能有{key - >的地图? Scala中的函数调用}?

时间:2011-02-14 17:15:23

标签: scala map reference function-pointers

我正在尝试创建一个包含键映射的类 - >函数调用,以下代码的行为不符合我的要求。

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

表示一旦将函数放入映射中,它就是一个冻结的实例(每个键为每个传递生成相同的值)。我希望看到的行为是键会引用一个函数调用,生成一个新的随机值,而不是只返回映射中保存的实例。

3 个答案:

答案 0 :(得分:16)

问题在于地图m的签名。您描述了要将功能放在地图中;但是你已经将它声明为Map[String, Double],它只是一个双打字符串的映射。正确的类型是Map[String, () => Double]

因为括号在无参数方法调用中是可选的,所以这里类型的差异非常重要。在填充地图时,在插入时调用方法以匹配类型签名(我相信这是通过隐式转换完成的,但我不是100%确定)。

只需更改地图的声明签名,即可根据需要插入函数,并可在computeValues期间进行评估(需要在第35行更改为map += {factor -> value()}),从而产生以下结果输出(在Scala 2.8上测试):

0.662682479130198
0.5106611727782306
0.6939805749938253
0.763581022199048
0.8785861039613938
0.9310533868752249

答案 1 :(得分:4)

您需要将键映射到函数,而不是映射到函数会给您的答案。试试这个:

var m = Map[String,() => Double]()
m += /* etc. */
m.values.foreach(println(x => x()))
m.values.foreach(println(x => x()))

答案 2 :(得分:0)

我会使用scala的类型推断来定义地图。 如果它们仅通过地图使用,则无需单独定义方法。 您也可以使用不可变的val,而不是可变的var。

val m = Map( "key1" -> {() => rnd.nextDouble},
  "key2" -> {() => rnd.nextDouble},
  "key3" -> {() => rnd.nextDouble},
  "key4" -> {() => rnd.nextDouble},
  "key5" -> {() => rnd.nextDouble})

您还需要将第35行更改为值()

相关问题