使代码的和平不可改变

时间:2013-06-26 05:37:00

标签: scala

我无法弄清楚如何使以下代码成为不可变的:

def function123(str: String, mapVal: Map[String, String]) = {
    var str1 = str
    mapVal.keySet.foreach({x => 
       str1 = str1.replaceAll(/*some pattern involving x*/, mapVal.get(x).get)})
    str1
}

我可以怀疑我会使用foldLeft或带参数累加器的嵌套方法,但这些只是我的想法。

那我该怎么做?

1 个答案:

答案 0 :(得分:5)

<强> foldLeft

你这里有一个循环。

带有副作用的循环的不可变版本是foldLeft,所有副作用都被下一个状态创建所取代:

val result = mapVal.foldLeft(str){case (state, (key, value)) => 
  state.replaceAll(/*some pattern involving key*/, value)
}

要在不可变环境中工作,每次循环迭代都应该返回值,并将前一次迭代的结果作为参数。这正是foldLeft的原因。

<强>递归

另一种解决方案是递归方法。您应该将循环迭代提取到方法,并使此方法最终调用下一个迭代:

def function123(str: String, mapVal: Map[String, String]) = {
  @tailrec def loop(state: String, pairs: List[(String, String)]): String = pairs match {
    case Nil => state
    case (key, value) :: tail =>
      val nextState = state.replaceAll(/*some pattern involving key*/, value)
      loop(nextState, tail)
  }
  loop(str, mapVal.toList)
}

可变循环 - &gt;不可变

要使具有可变循环的代码成为不可变的,你应该将循环中变化中隐含的所有值提取到某种状态(foldLeft的单个状态对象或递归方法的一组参数)然后生成基于每次迭代结束时的前一个新状态。