Почему оператор + для List не поддерживается в Scala? - PullRequest
13 голосов

Ответы [ 4 ]

16 голосов
/ 23 января 2010

Хороший вопрос, поэтому я посмотрел его в книге Odersky et al. В нем говорится следующее (надеюсь, это не нарушение авторских прав, если процитировать это здесь; -)):


Почему бы не добавить в списки?

Класс List не предлагает операцию добавления, потому что время, необходимое для добавления в список, растет линейно с размером списка, тогда как добавление с :: занимает постоянное время. Если вы хотите построить список, добавляя элементы, вы можете добавить их заранее, затем, когда вы закончите, позвоните reverse; или используйте ListBuffer, изменяемый список, который предлагает операцию добавления, и когда вы закончите, наберите toList.


Насколько я понимаю, FP добавление к списку встречается гораздо чаще, чем добавление, по крайней мере, на чисто функциональных языках. Я могу только предположить, что разработчики Scala добавили оператор + для удобства разработчиков Java, которые привыкли добавлять с помощью add(), а потом подумали об этом.

14 голосов
/ 23 января 2010

устарела в мае 2008 года в редакция 15071 с сообщением:

Удалите все проблемные + методы и удалите те, которые никогда не появлялись в выпуске.

Я ожидаю, что это должно было избежать двусмысленности с StringAdd # +. Сравните разницу между 2.7.6 и 2.8.0 бета ниже:

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 Мартин Одерский отмечает:

Чтобы узнать, что на самом деле плохо Список # +, подумайте, что вы ожидаете следующее для производства:

Список (1, 2, 3) + "правильный результат "

oxbow_lakes добавляет - мне потребовалось некоторое время, чтобы распаковать этот загадочный комментарий, но я думаю, дело в том, что он нарушит коммутативность типов, подразумеваемую оператором +. То есть тип a + b должен совпадать с типом b + a

UPDATE Уточнение Мартина Одерского:

Что бы вы ожидали

Список (1, 2, 3) + «правильный результат»

производить? Я ожидал бы строку: «Список (1, 2, 3) - правильный результат».

С 2.7 стилем List. + Вы получите вместо Список [Любой], Список (1, 2, 3, «это правильный результат ").

Я классифицирую это как неприятный сюрприз. В Резюме, никогда не должно быть + метод для коллекций, ковариантных по типу элемента. наборы и карты не вариантные, поэтому у них может быть + метод. Это все довольно деликатный и грязный. Мы бы лучше, если мы не будем пытаться дубликат Java + для строки конкатенации. Но когда Скала получила разработал идею было сохранить по существу, все выражения Java синтаксис, включая String +. И его слишком поздно, чтобы изменить это сейчас.

11 голосов
/ 23 января 2010

Он не был коммутативным и был особенно неоптимальным в списках. Кроме того, поведение отличается между изменчивыми и неизменяемыми коллекциями. На Scala 2.8 у вас есть следующее:

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

Изменчивая / неизменная вещь не совсем решена. В качестве первого шага группа методов устарела, но их нельзя изменить или полностью удалить без предварительного периода устаревания.

3 голосов
/ 23 января 2010

Если вы будете следовать этой теме , вы увидите, что, вероятно, это связано с проблемой производительности.

Как правило, нужно организовать List конструкцию, чтобы не дописывать. Scala's List - это неизменяемый единый связанный список, поэтому добавление в его конец - операция O (n).

ListA ::: ListB является ассоциативным справа и выполняется во времени, пропорциональном длине ListA a ::: b - это / prepend / операция, которая выполняется в O(a.length) время

...