Почему оператор + для списка устарел в Scala?
Почему оператор + для списка устарел в Scala?
http://www.scala-lang.org/docu/files/api/scala/List.html#%2B%28B%29
Ответы
Ответ 1
Хороший вопрос, поэтому я просмотрел его в книге Odersky et al. В нем говорится следующее (надеюсь, это не нарушение авторских прав, чтобы процитировать это здесь: -)):
Почему бы не добавить в списки?
Класс List
не предлагает операцию добавления, поскольку время, которое требуется для добавления в список, растет линейно с размером списка, тогда как добавление с ::
занимает постоянное время. Ваши параметры, если вы хотите создать список, добавляя элементы, - это добавить их, а затем, когда вы закончите, вызовите reverse
; или используйте ListBuffer
, измененный список, который предлагает операцию добавления, и когда вы закончите вызов toList
.
Насколько я понимаю FP, добавление к списку гораздо чаще, чем добавление, по крайней мере, на чистых функциональных языках. Я могу только предположить, что дизайнеры Scala добавили оператор +
в качестве удобства для разработчиков Java, которые используются для добавления с помощью add()
, а затем подумали об этом.
Ответ 2
В мае 2008 года он был устаревшим в версии 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
UPDATE
В списке scala -user Мартин Одерский отмечает:
Чтобы узнать, что действительно плохо Список # +, подумайте, что вы ожидаете для получения:
Список (1, 2, 3) + "является правильным результат"
?
oxbow_lakes добавляет - мне потребовалось некоторое время, чтобы распаковать этот критический комментарий, но я думаю, что дело в том, что оно нарушит коммутативность типов, подразумеваемых оператором +
. То есть тип a + b
должен быть таким же, как тип b + a
UPDATE
Прояснение Мартина Одерского:
Что вы ожидаете
Список (1, 2, 3) + "- правильный результат"
производить? Я бы ожидал строку: "Список (1, 2, 3) - правильный результат".
С 2,7 списком стилей + вы получаете вместо этого Список [Any], List (1, 2, 3, "является правильный результат" ).
Я классифицирую это как плохой сюрприз. В резюме, никогда не должно быть + метод для коллекций, ковариантных по типу элементов. наборы и карты не являются вариантами, поэтому они могут иметь + метод. Все это довольно деликатный и грязный. Мы будем лучше, если бы мы не пытались дублировать Java + для строки конкатенации. Но когда Scala получил Идея заключалась в том, чтобы по существу, все выражения Java синтаксис, включая String+. И это слишком поздно, чтобы изменить это сейчас.
Ответ 3
Он не был коммутативным и был особенно субоптимален в списках. Кроме того, поведение отличается от изменчивых и неизменных коллекций. На Scala 2.8 у вас есть следующее:
element +: sequence // prepend
sequence :+ element // append
sequenece ++ sequence // concatenate
Изменчивая/непреложная вещь не совсем решена. Несколько методов были устаревшими в качестве первого шага, но они не могут быть изменены или удалены без предварительного устаревания.
Ответ 4
Если вы следуете этот поток, вы увидите, что это, вероятно, проблема с производительностью.
Как правило, следует организовать конструкцию List
, чтобы не добавлять. Scala Список - это неизменный одиночный связанный список, поэтому добавление к его концу - операция O (n).
ListA ::: ListB
является право-ассоциативным и работает во времени, пропорциональном длине ListA 'a ::: b
' - это операция /prepend/operation, которая выполняется в O(a.length)
time