Existe alguma diferença entre :::
e ++
para concatenar listas no 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
A partir da documentação , parece ++
ser mais geral, enquanto :::
é List
específico. O último é fornecido porque é usado em outras linguagens funcionais?
list
scala
concatenation
Luigi Plinge
fonte
fonte
:::
é um operador de prefixo, como todos os métodos iniciados com:
Respostas:
Legado. A lista foi originalmente definida para aparência de idiomas funcionais:
Obviamente, Scala desenvolveu outras coleções, de maneira ad-hoc. Quando o 2.8 foi lançado, as coleções foram redesenhadas para reutilização máxima de código e API consistente, para que você possa usar
++
para concatenar quaisquer duas coleções - e até iteradores. A List, no entanto, conseguiu manter seus operadores originais, além de um ou dois que foram preteridos.fonte
:::
favor do++
agora? Também use em+:
vez de::
?::
é útil devido à correspondência de padrões (consulte o segundo exemplo de Daniel). Você não pode fazer isso com+:
List
vez deSeq
, também poderá usarList
métodos idiomáticos . Por outro lado, dificultará a mudança para outro tipo, se você desejar fazer isso.::
e:::
) e operações mais gerais que são comuns a outras coleções. Eu não abandonaria nenhuma das operações do idioma.:+
e+:
objetos.Sempre use
:::
. Há duas razões: eficiência e segurança do tipo.Eficiência
x ::: y ::: z
é mais rápido quex ++ y ++ z
, porque:::
é associativo correto.x ::: y ::: z
é analisado comox ::: (y ::: z)
, o que é algoritmicamente mais rápido que(x ::: y) ::: z
(o último requer O (| x |) mais etapas).Digite segurança
Com
:::
você só pode concatenar doisList
s. Com++
você, você pode anexar qualquer coleção aList
, o que é terrível:++
Também é fácil misturar-se com+
:fonte
x ::: y ::: z
deve ser substituído porList(x, y, z).flatten
. pastebin.com/gkx7Hpadx
ey
(z
nunca é iterada em nenhum caso; portanto, não afeta o tempo de execução, é por isso que é melhor anexar uma lista longa a uma curta, do que o contrário), mas complexidade assintótica não conta a história toda.x ::: (y ::: z)
iteray
e acrescentaz
, depois iterax
e acrescenta o resultado dey ::: z
.x
ey
são iterados uma vez.(x ::: y) ::: z
iterax
e acrescentay
, depois itera o resultado dex ::: y
e acrescentaz
.y
ainda é iterado uma vez, masx
é iterado duas vezes neste caso.:::
funciona apenas com listas, enquanto++
pode ser usado com qualquer travável. Na implementação atual (2.9.0),++
recai novamente:::
se o argumento também for aList
.fonte
Um ponto diferente é que a primeira frase é analisada como:
Enquanto o segundo exemplo é analisado como:
Portanto, se você estiver usando macros, tome cuidado.
Além disso,
++
para duas listas está chamando,:::
mas com mais sobrecarga porque está solicitando um valor implícito para ter um construtor de Lista para Lista. Mas as marcas de microbench não provaram nada de útil nesse sentido, acho que o compilador otimiza essas chamadas.Micro-benchmarks após o aquecimento.
Como Daniel C. Sobrai disse, você pode anexar o conteúdo de qualquer coleção a uma lista usando
++
, enquanto que:::
você só pode concatenar listas.fonte