如何在 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
,其中:
- 您无法控制的客户端代码 可能会向您发送一个可变的
Seq
,并且
- 收到的集合的不变性至关重要。
我今天了解到 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
,其中:
- 您无法控制的客户端代码 可能会向您发送一个可变的
Seq
,并且 - 收到的集合的不变性至关重要。