如何在 Scala 中默认使用不可变的 Seq?

How to default to immutable Seq in scala?

我今天了解到 scala 的 Seq 可能意味着可变或不可变的 Seq 都可以实现其类型别名。 (我偶然发现 blogpost 谈论它。)

在我的代码库中,我尝试遵循函数式编程最佳实践,虽然我确实假设 Seq 强制执行不可变序列,但它可能不是,因此会导致意外副作用的入口点。

为了防止可变 Seq,我可以使用 Sequence 键入我的函数:

scala.collection.immutable.Seq 在我期望 Seq.

的每个文件中

我也不喜欢阅读我的代码库中的 immutable.Seq

对我来说,Seq 应该像 Set 别名一样,默认情况下是不可变的。

有没有一种方法可以使默认 Seq 别名指向我的项目的不可变对应物而不妨碍供应商导入?

我不建议尝试破坏默认的 Scala 行为。除非你定义自己的函数接受任何输入和 returns 该输入的不可变序列,否则我认为只使用 immutable.Seq

是最安全的

你总是可以尝试这样的事情(没有经过彻底测试):

def seq(inputs: Any*): scala.collection.immutable.Seq[Any] = {
  scala.collection.immutable.Seq(inputs)
}

scala> seq("hi", true)
res0: scala.collection.immutable.Seq[Any] = List(WrappedArray(hi, true))

scala> seq(1, 'c', "string", false)
res1: scala.collection.immutable.Seq[Any] = List(WrappedArray(1, c, string, false))

编辑:

按照jwvh pointed out, this option isn't ideal. Using generic types like James Whiteley的建议,如果你坚持自己做函数可能会更好:

def seq[T](inputs: T*): scala.collection.immutable.Seq[T] =
  scala.collection.immutable.Seq(inputs).flatten

这输出:

scala> seq("hi", true)
res0: scala.collection.immutable.Seq[Any] = List(hi, true)

但我要重申 - 最好在需要的地方使用 immutable.Seq,或者寻找其他集合类型来使用。

好的,阅读了(4 岁的)博客 post,我真的不认为这是什么大问题。

默认的 Seq()collection.Seq,它本身不可变,但它是可变和不可变变体的父级。因此,创建和传递默认 Seq 集合的代码不会受到影响,但接受 Seq 参数的代码 可能 会收到 mutable.Seq。但这只是一个问题,如果不可变性不仅是假设而且是必需的,例如为了线程安全。

底线:在这些文件的顶部放置一个 import collection.immutable.Seq,其中:

  1. 您无法控制的客户端代码 可能会向您发送一个可变的 Seq,并且
  2. 收到的集合的不变性至关重要。