为什么在Scala中不推荐使用List的+运算符?

时间:2010-01-23 13:34:57

标签: list scala operator-overloading deprecated

为什么在Scala中不推荐使用List的+运算符?

http://www.scala-lang.org/docu/files/api/scala/List.html#%2B%28B%29

4 个答案:

答案 0 :(得分:16)

好问题,所以我在Odersky等人的书中查阅了它。它说下面的内容(希望在这里引用它不是版权侵权; - )):


为什么不附加到列表?

List不提供追加操作,因为追加到列表所需的时间与列表的大小呈线性增长,而前置::则需要一段时间。如果你想通过追加元素来建立一个列表,那么你的选择就是先添加它们,然后当你完成调用时reverse;或者使用ListBuffer,一个提供追加操作的可变列表,并在您完成后拨打toList


据我了解FP,前缀列表比附加更常见,至少在纯函数式语言中是这样。我只能假设Scala的设计者添加了+运算符,以方便Java开发人员,他们习惯使用add()进行追加,然后再次考虑它。

答案 1 :(得分:14)

2008年5月在revision 15071中弃用了该消息:

  

弃用所有有问题的+方法,并删除那些从未出现在版本中的方法。

我希望这是为了避免使用StringAdd#+产生歧义。比较下面2.7.6和2.8.0 Beta之间的差异:

Welcome to Scala version 2.7.6.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_15).
Type in expressions to have them evaluated.
Type :help for more information.

scala> List(1) + 2
warning: there were deprecation warnings; re-run with -deprecation for details
res0: List[Int] = List(1, 2)

scala> List(1) + "2"
warning: there were deprecation warnings; re-run with -deprecation for details
res1: List[Any] = List(1, 2)

在2.8中,该方法已被删除,您将获得:

Welcome to Scala version 2.8.0.Beta1-RC8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_15).
Type in expressions to have them evaluated.
Type :help for more information.

scala> List(1) + 2
<console>:5: error: type mismatch;
 found   : Int(2)
 required: String
       List(1) + 2
                 ^

scala> List(1) + "2"
res1: java.lang.String = List(1)2

<强>更新

在scala-user列表中,Martin Odersky指出:

  

找出真正的坏事   列出#+,考虑一下你的期望   以下产生:

     

列表(1,2,3)+“是正确的   结果“

     

oxbow_lakes添加 - 我花了一段时间来解开这个神秘的评论,但我认为重点是它会违反+运算符隐含的类型的交换性。也就是说,a + b的类型应与b + a

的类型相同

<强>更新 Martin Odersky的澄清:

  

您期望什么

     
    

列表(1,2,3)+“是正确的结果”

  
     

生产?我希望有一个字符串:   “列表(1,2,3)是正确的结果”。

     

使用2.7样式列表。+,您可以获得   列表[任意],列表(1,2,3,“是   正确的结果“)。

     

我认为这是一个不好的惊喜。在   总结,一个人应该永远不会有   +对元素类型中协变的集合的方法。集   和地图是非变体的,这就是原因   他们可以有+方法。这就是全部   相当精致和凌乱。我们会的   如果我们不尝试,那就更好了   复制Java的+用于String   级联。但当斯卡拉得到   设计的想法是保持   基本上所有Java的表达方式   语法,包括String +。它就是   来不及改变现在。

答案 2 :(得分:11)

这不是可交换的,在名单上尤其不是最理想的。此外,可变和不可变集合之间的行为也不同。在Scala 2.8上,您有以下内容:

element +: sequence   // prepend
sequence :+ element   // append
sequenece ++ sequence // concatenate

可变/不可变的事情还没有完全解决。一堆方法作为第一步被弃用,但是在没有弃用期的情况下,它们不能被更改或彻底删除。

答案 3 :(得分:3)

如果您关注this thread,您会发现可能是性能问题。

  

一般来说,应该安排List构造以便不附加。   Scala的List是一个不可变的单链表,因此追加到它的末尾是O(n)操作。

     

ListA ::: ListB是右关联的,并且在时间上与ListA的长度成比例   “a ::: b”是/ prepend / operation,在O(a.length)时间内运行