Rob*_*ier 16

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


为什么不附加到列表?

List不提供追加操作,因为追加到列表所花费的时间与列表的大小呈线性增长,而前置则::需要恒定的时间.如果你想通过附加元素来建立一个列表,你的选择是先添加它们,然后当你完成调用时reverse; 或者使用a ListBuffer,提供追加操作的可变列表,以及完成呼叫时toList.


据我了解FP,前缀列表比附加更常见,至少在纯函数式语言中是这样.我只能假设Scala的设计者添加了+运算符,以方便Java开发人员,他们习惯于使用它add(),然后对它有了第二个想法.

  • 实际上,这甚至不是真正的 FP 问题,它是持久递归链表工作方式的一般特征:前置是更新单个指针/引用/任何您想调用的内容,附加需要复制整个列表。所以,前置是`O(1)`,带有一个很小的常数因子,附加是`O(n)`,带有一个相当大的`c`。 (2认同)
  • 那么,"O(n)"复杂性是由于需要复制列表而产生的,这是因为需要具有不可变列表.仅使用不可变数据是函数式编程语言的标志.所以我仍然会说它是FP的东西.在Java的列表类型中,或者例如C++附加中的`std :: list :: push_back`有`O(1)`. (2认同)

ret*_*nym 14

它于2008年5月在修订版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)
Run Code Online (Sandbox Code Playgroud)

在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
Run Code Online (Sandbox Code Playgroud)

UPDATE

在scala用户列表中,Martin Odersky指出:

要找出List#+的真正坏处,请考虑您希望以下内容产生的内容:

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

oxbow_lakes补充道 - 我花了一段时间来解开这个神秘的评论,但我认为重点是它会违反+运营商隐含的类型的可交换性.也就是说,类型a + b应该与类型相同b + a

更新 Martin Odersky的澄清:

你会期待什么?

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

生产?我希望有一个字符串:"List(1,2,3)是正确的结果".

使用2.7样式List.+,您可以获得List [Any],List(1,2,3,"是正确的结果").

我认为这是一个不好的惊喜.总之,对于在元素类型中具有协变性的集合,应该永远不会有+方法.集合和映射是非变量的,这就是为什么它们可以有+方法.这一切都相当精致和凌乱.如果我们不尝试复制Java的+用于字符串连接,我们会更好.但是当Scala得到设计时,我们的想法就是保留Java的所有表达式语法,包括String +.现在改变它已经太晚了.


Dan*_*ral 11

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

element +: sequence   // prepend
sequence :+ element   // append
sequenece ++ sequence // concatenate
Run Code Online (Sandbox Code Playgroud)

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