scala - 最佳实践 : "If not immutable create copy"-pattern

标签 scala immutability scala-collections

我有一个函数,它获取一个 Seq[_] 作为参数,并返回一个不可变的类实例,这个 Seq 作为 val 成员。如果 Seq 是可变的,我显然想创建一个防御性副本以保证我的返回类实例不能被修改。

此模式的最佳实践是什么?首先,令我感到惊讶的是不可能重载该函数

  def fnc(arg: immutable.Seq[_]) = ...
  def fnc(arg: mutable.Seq[_]) = ...

我也可以进行模式匹配:

  def fnc(arg: Seq[_]) = arg match {
    case s: immutable.Seq[_] => { println("immutable"); s}
    case s: mutable.Seq[_] => {println("mutable"); List()++s }
    case _: ?
  }   

但我不确定 _ 的情况。是否保证 argimmutable.Seqmutable.Seq?我也不知道 List()++s 是否是转换它的正确方法。我看到很多关于 SO 的帖子,但其中大部分都是针对 2.8 或更早版本的。

Scala-Collections 是否足够“智能”,以至于我总是可以(无需模式匹配)编写 List()++s 并且如果不可变我得到相同的实例,如果可变我得到深拷贝?

推荐的方法是什么?

最佳答案

如果你想同时支持两者,你将需要模式匹配。 Seq()++ 的代码保证(作为其 API 的一部分)如果它是不可变的,它不会复制其余部分:

scala> val v = Vector(1,2,3)
v: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> Seq() ++ v
res1: Seq[Int] = List(1, 2, 3)

对于某些特殊情况,它可能会自行进行模式匹配,但您知道自己想要的情况。所以:

def fnc[A](arg: Seq[A]): Seq[A] = arg match {
  case s: collection.immutable.Seq[_] => arg
  case _ => Seq[A]() ++ arg
}

你不必担心 _;这只是说你不关心类型参数到底是什么(不是你可以检查),如果你这样写,你不会:如果不可变则通过,否则复制。

关于scala - 最佳实践 : "If not immutable create copy"-pattern,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14302156/

相关文章:

data-structures - 关系数据库的高效持久数据结构

scala - 如何在 Scala 中使用优先队列?

scala - 为什么方法 "combinations"在 Scala 中返回 Iterator 而不是 Stream?

java - Scala.List 和 Java.util.List 之间的互操作

scala - 使用 Scala 发送击键和鼠标点击

java - 如何通过时间戳属性过滤对象数组(通过 - 命令分区的 SQL 滞后的替代代码)

scala - 如何将闪存数据从 Controller 传递到 Play! 中查看框架

java - 我是否需要防御性复制来构造一个具有*非最终*但不可变字段的不可变类?

scala - 不包含a的集合,其中a⊆b和b在集合中

Java:不可变类的伪setter方法