scala - 使代码的和平不可变

标签 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 或带有参数累加器的嵌套方法,但这只是我的想法。

那我该怎么做呢?

最佳答案

向左折叠

这里有一个循环。

具有副作用的不可变循环版本是 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)
}

可变循环 -> 不可变

要使具有可变循环的代码成为不可变的,您应该将循环内更改中隐式涉及的所有值提取到某种状态(foldLeft 的单个状态对象或递归方法的一堆参数)然后在每次迭代结束时基于先前的状态产生一个新的状态。

关于scala - 使代码的和平不可变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17312271/

相关文章:

scala - 在 Scala 中,有没有办法将价格表示为 $Y.YY?

scala - 如何在字符串类型的嵌套结构中获取spark中的所有列名称

scala - 如何将 Scalaz 的 traverse 和 traverseU 与 Either 结合使用

scala - 列出Scala中非默认文件系统上的文件

scala - 解除Shtml.link

debugging - Scala IDE 调试器 "step into"行为

scala - 为什么persist()在Spark中被惰性求值

function - Scala val 语法 : What does val myVal:{ def . .. } 是什么意思?

scala - 使用 sbt 和 testng 时,如何获得测试中引发的异常的完整堆栈跟踪?

scala - 如何从现有的 SparkContext 创建 SparkSession