【问题标题】:How to default to immutable Seq in scala?如何在scala中默认为不可变Seq?
【发布时间】:2018-09-06 04:13:58
【问题描述】:

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

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

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

scala.collection.immutable.Seq 在我期待Seq 的每个文件中。

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

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

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

【问题讨论】:

  • 为什么说Seq默认是可变的? collection.mutable.Sequpdate() 方法,但 collection.Seq 没有。
  • 是的,我在这里遗漏了什么吗?我已经使用Seq 有一段时间了,但从未见过它可变的地方。我们说的是从Seq.apply(1, 2, 3) 返回的Seq 对吧?
  • @jwvh 我重新表述了我的问题。
  • @JordanCutler 我说的是这里指出的内容:orrsella.com/2014/02/27/…

标签: scala functional-programming sequence immutability seq


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    我不建议尝试使用默认的 Scala 行为。除非您定义自己的函数来接受任何输入并返回该输入的不可变 Seq,否则我认为使用 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 指出的那样,这个选项并不理想。如果您坚持制作自己的函数,建议使用像 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,或者找到其他要使用的集合类型。

    【讨论】:

    • 您也可以使用泛型类型编写函数:def seq[T](inputs: T*): scala.collection.immutable.Seq[T] = scala.collection.immutable.Seq(inputs).flatten
    • 这将使输出为res0: scala.collection.immutable.Seq[Any] = List(hi, true)等。
    • 这看起来是个糟糕的主意。你失去了所有类型的安全性,结果seq 有一个元素,WrappedArray
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-23
    相关资源
    最近更新 更多