【问题标题】:scala: how to avoid mutation?scala:如何避免突变?
【发布时间】:2012-02-21 16:13:33
【问题描述】:

当人们需要积累一些数据时,这是司空见惯的事情。我习惯这样做的方式是将数据块附加到数组中。但这在 scala 中是一种不好的做法,那么我该如何避免呢?

【问题讨论】:

  • 如果您能给我们一些示例代码来说明您要实现的目标,那就太好了……对于一些常见情况,foldLeft/foldRight 可以完成这项工作:scala-lang.org/api/current/scala/collection/immutable/…
  • 这个问题非常广泛。请澄清它,提供示例等。

标签: scala mutation


【解决方案1】:

嗯,有两种处理累加的通用方法:递归和折叠。让我们看一下每个非常简单的示例,以计算列表值的总和。

def sumRecursively(list: List[Int]): Int = {
  def recurse(list: List[Int], acc: Int): Int =
    if (list.isEmpty) acc
    else recurse(list.tail, acc + list.head)
  recurse(list, 0)
}

def sumFolding(list: List[Int]): Int =
  list.foldLeft(0){ case (acc, n) => acc + n }

这有很多变体,可以更好地处理一种或另一种情况。

【讨论】:

  • 将这两种方式称为“两种”方式似乎很奇怪,因为折叠只是特定递归模式的抽象。
  • @DanBurton 如果您认为 fold 是递归类型的变态,那么您就不会问这个问题了,对吗?就整个世界而言,折叠是一个循环。
【解决方案2】:

其实不然。您可以在 scala 中使用 Vector,默认情况下它是 scala.collection.immutable 包的一部分。这将创建一个不可变集合,每次附加到它时都会返回一个新的(不同的)实例。

更多信息:

http://www.scala-lang.org/docu/files/collections-api/collections_15.html

【讨论】:

    【解决方案3】:

    对于最常见的用途,“map”和“flatMap”操作用于在功能上生成数据结构。两者都从一个数据结构开始,对其中的每个元素应用一些操作,并返回一个与原始数据结构相同形状的新数据结构。它们的不同之处在于新数据结构的填充方式。这两个是如此常见且如此强大,以至于 Scala 包含了一种特殊的语法 for-comprehension 来支持它们。 for-comprehension 表面上看起来类似于 Java 风格的 for 循环,但实际上编译为一系列 map 和 flatMap 调用(以及其他一些调用)。

    在函数式编程中,通常将问题分解为从一种数据结构到另一种数据结构的转换,而不是明确描述构建和销毁数据结构所需的步骤。这需要一些时间来适应,尤其是在弄清楚要开始使用什么数据结构时。一旦你掌握了它,这是一种非常强大的技术,可以清晰、准确地表达大量功能,并且几乎没有 bug 潜入的空间。

    还值得注意的是,“map”和“flatMap”实际上都是另一个更强大的函数的特例:“fold”。 “fold”(出于技术原因同时实现为“foldLeft”和“foldRight”)可用于构建数据结构和分解它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-01
      • 2018-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多