简体   繁体   English

如何在Scala中默认为不可变Seq?

[英]How to default to immutable Seq in scala?

I learned today that scala's Seq can mean that both a mutable or immutable Seq can fulfill its type alias. 我今天了解到,scala的Seq可能意味着可变或不变的Seq都可以满足其类型别名。 (I stumbled over a blogpost talking about it.) (我偶然发现了一个谈论它的博客 。)

In my codebase, I try to follow functional programming best practices and while I did assume Seq to enforce an immutable Sequence, it may not be and hence causing an entry-point for unintended side-effects. 在我的代码库中,我尝试遵循函数式编程最佳实践,尽管我确实假定Seq强制执行不可变序列,但可能并非如此,因此会导致意外副作用的切入点。

In order to protect against mutable Seq I could type my functions using a Sequence with: 为了防止可变的Seq,我可以使用带有以下内容的Sequence键入我的函数:

scala.collection.immutable.Seq in each of my files in which I am expecting a Seq . 我希望在每个文件中使用Seq scala.collection.immutable.Seq

I also do not prefer to read immutable.Seq in my code base. 我也不喜欢在我的代码库中读取immutable.Seq

For me, Seq should behave just like Set alias and be immutable by default. 对我来说, Seq行为应类似于Set别名,并且默认情况下是不可变的。

Is there a way I can make the default Seq alias to point to its immutable counterpart for my project without hindering vendor imports? 有没有一种方法可以使我的项目使用默认的Seq别名指向其不变的副本,而又不妨碍供应商的进口?

I wouldn't recommend trying to mess with default Scala behaviour. 我不建议您尝试破坏默认的Scala行为。 Unless you define your own function which takes any input and returns an immutable Seq of that input, I think it'd be safest to just use immutable.Seq 除非您定义自己的函数以接收任何输入并返回该输入的不可变Seq,否则我认为仅使用immutable.Seq是最安全的

You can always try something like this (not thoroughly tested): 您可以随时尝试以下操作(未经全面测试):

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))

Edit: 编辑:

As jwvh pointed out, this option isn't ideal. 正如jwvh所指出的,该选项不是理想的。 Using generic types like James Whiteley suggested could be better if you insist on making your own function: 如果您坚持要创建自己的函数,那么建议使用像James Whiteley这样的泛型类型会更好:

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

This outputs: 输出:

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

But I'll reiterate - it might just be best to use immutable.Seq where needed, or find another collection type to use. 但我要重申-可能最好是在需要的地方使用immutable.Seq ,或者找到另一个要使用的集合类型。

OK, having read the (4-year old) blog post, I really don't see this as being much of an issue. 好吧,在阅读了(已有4年历史的)博客文章之后,我真的认为这不是什么大问题。

The default Seq() is collection.Seq which isn't mutable itself, but it is the parent of both the mutable and immutable variants. 默认的Seq()collection.Seq本身不是可变的,但它是可变和不可变变量的父代。 So code that creates and passes default Seq collections isn't effected but code that accepts a Seq parameter might receive a mutable.Seq . 因此,创建并传递默认Seq集合的代码不会受到影响,但是接受Seq参数的代码可能会收到mutable.Seq But that's only an issue if immutability is not just assumed but required, eg for thread safety. 但这仅是不可变性的前提条件,例如线程安全性,这只是一个问题。

Bottom line: Put an import collection.immutable.Seq at the top of those files where: 底线:在这些文件的顶部放置一个import collection.immutable.Seq ,其中:

  1. Client code that you don't control might send you a mutable Seq , and 您无法控制的客户端代码可能会向您发送可变的Seq ,并且
  2. The immutability of that received collection is of paramount importance. 收到的收藏品的不变性至关重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM