scala:以编程方式更改功能

时间:2015-09-24 21:13:27

标签: scala

请考虑以下代码段:

  def fun1(x:T): String = // something here 

  var grandFun = { 
    t: T => Map('key1 -> fun1(t))
  }

问题是,是否可以以编程方式grandFun内的地图添加新功能? 基本上,填写以下功能:

def addFunToMyGrandFun(fun: T => String): Unit = { 
   // add fun go the `grandFun`
}

这样给:

def fun2(x:T): String = // something here 

运行addFunToMyGrandFun(fun2)后,grandFun会更新为以下内容:

var grandFun = { 
  t: T => Map('key1 -> fun1(t), 'key2 -> fun2(t))
}    

2 个答案:

答案 0 :(得分:3)

您可以在函数外部定义一个仅存储函数的映射。然后,您可以在函数中使用此贴图,并在地图中应用函数以获取所需的贴图。

如果您使用mutable.Map,则可以向地图添加新功能。在toMap上拨打mutable.Map会返回immutable.Map

import scala.collection.mutable.{Map => MutableMap}

val functionMap = MutableMap.empty[Symbol, T => String]
val grandFun = (t: T) => functionMap.mapValues(f => f(t)).toMap

例如,如果TInt

val yourMap = MutableMap.empty[Symbol, Int => String]
val grandFun = (n: Int) => functionMap.mapValues(f => f(n)).toMap

yourMap += 'key1 -> ((_: Int).toString)
grandFun(5) // Map('key1 -> 5)

yourMap += 'key2 -> ((_: Int).toString * 5)
grandFun(10) // Map('key2 -> 55555, 'key1 -> 5)

答案 1 :(得分:2)

如果您的密钥只是String而不是符号,那么我认为类似下面的类应该封装您的意图:

case class GrandFun[T,R](funs: Map[String, Function1[T,R]], count: Int) {

  def addFun(fun: T => R) = {
    val key = s"key$count"
    GrandFun(funs + (key -> fun), count + 1)
  }

  def apply(t: T) = funs mapValues { fun => fun(t) }
}

object GrandFun {
  def apply[T,R](): GrandFun[T,R] = new GrandFun(Map.empty[String,Function1[T,R]], 0)
}

使用示例:

scala> val gf = GrandFun[Int, String]
gf: GrandFun[Int,String] = GrandFun(Map(),0)

scala> val gf1 = gf.addFun(fun1)
gf1: GrandFun[Int,String] = GrandFun(Map(key0 -> <function1>),1)

scala> def fun1(t: Int): String = t.toString
fun1: (t: Int)String

scala> def fun2(t: Int): String = (t+2).toString
fun2: (t: Int)String

scala> val gf1 = gf.addFun(fun1)
gf1: GrandFun[Int,String] = GrandFun(Map(key0 -> <function1>),1)

scala> val gf2 = gf1.addFun(fun2)
gf2: GrandFun[Int,String] = GrandFun(Map(key0 -> <function1>, key1 -> <function1
>),2)

scala> gf2(4)
res7: scala.collection.immutable.Map[String,String] = Map(key0 -> 4, key1 -> 6)

请注意,我选择将GrandFun设为不可变,但您也可以使用可变形式,例如:

class GrandFun[T,R] {
  private var funs = Map[String, Function1[T,R]]()
  private var count = 1

  def addFun(fun: T => R) {
    val key = s"key$count"
    count += 1
    funs = funs + (key -> fun)
  }

  def apply(t: T) = funs mapValues { fun => fun(t) }
}