Есть ли разница между :::
и ++
для объединения списков в Scala?
scala> List(1,2,3) ++ List(4,5)
res0: List[Int] = List(1, 2, 3, 4, 5)
scala> List(1,2,3) ::: List(4,5)
res1: List[Int] = List(1, 2, 3, 4, 5)
scala> res0 == res1
res2: Boolean = true
Из документации это выглядит как ++
более общий, тогда :::
как List
-специфичный. Предоставляется ли последний, потому что он используется в других функциональных языках?
list
scala
concatenation
Луиджи Плинге
источник
источник
:::
является префиксным оператором, как и все методы, начинающиеся с:
Ответы:
Наследие. Первоначально список был определен как выглядящий на функциональных языках:
Конечно, Scala разработал другие коллекции, в особой манере. Когда вышел 2.8, коллекции были перепроектированы для максимального повторного использования кода и согласованного API, так что вы можете использовать их
++
для объединения любых двух коллекций - и даже итераторов. Список, однако, должен сохранить свои оригинальные операторы, кроме одного или двух, которые устарели.источник
:::
в пользу++
? Также используйте+:
вместо::
?::
полезно из-за сопоставления с образцом (см. второй пример Дэниела). Вы не можете сделать это с+:
List
вместоSeq
, вы можете использовать идиоматическиеList
методы. С другой стороны, будет сложнее перейти на другой тип, если вы когда-нибудь захотите это сделать.::
и:::
), и более общие операции, которые являются общими для других коллекций. Я бы не бросил ни одну операцию из языка.:+
и+:
экстракторы объектов.Всегда используйте
:::
. Есть две причины: эффективность и безопасность типов.КПД
x ::: y ::: z
быстрее, чемx ++ y ++ z
, потому что:::
это право ассоциативно.x ::: y ::: z
анализируется какx ::: (y ::: z)
, что алгоритмически быстрее, чем(x ::: y) ::: z
(последний требует O (| x |) больше шагов).Тип безопасности
При этом
:::
можно объединить только дваList
с. С помощью++
него можно добавить любую коллекциюList
, которая ужасна:++
также легко смешивается с+
:источник
x ::: y ::: z
следует заменить наList(x, y, z).flatten
. pastebin.com/gkx7Hpadx
иy
(z
никогда не повторяется ни в коем случае, поэтому не влияет на время выполнения, поэтому лучше добавлять длинный список в короткий, чем наоборот), но асимптотическая сложность не рассказывает всей истории.x ::: (y ::: z)
повторяетy
и добавляетz
, затем повторяетx
и добавляет результатy ::: z
.x
иy
оба повторяются один раз.(x ::: y) ::: z
повторяетx
и добавляетy
, затем повторяет результатx ::: y
и добавляетz
.y
все еще повторяется один раз, ноx
повторяется дважды в этом случае.:::
работает только со списками, в то время как++
может использоваться с любым перемещаемым. В текущей реализации (2.9.0)++
возвращается значение,:::
если аргумент также являетсяList
.источник
Другое дело, что первое предложение анализируется как:
В то время как второй пример анализируется как:
Поэтому, если вы используете макросы, вам следует позаботиться.
Кроме того,
++
для двух списков вызывается,:::
но с большими накладными расходами, потому что он запрашивает неявное значение для построения компоновщика из списка в список. Но микробенчмарки не доказали ничего полезного в этом смысле, я думаю, что компилятор оптимизирует такие вызовы.Микро-эталоны после прогрева.
Как сказал Даниэль С. Собрай, вы можете добавлять содержимое любой коллекции в список, используя
++
, тогда как:::
вы можете только объединять списки.источник