Y a-t-il une différence entre :::
et ++
pour concaténer des listes dans 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
D'après la documentation, il semble être ++
plus général alors qu'il :::
est List
spécifique. Ce dernier est-il fourni car il est utilisé dans d'autres langages fonctionnels?
list
scala
concatenation
Luigi Plinge
la source
la source
:::
un opérateur de préfixe comme toutes les méthodes commençant par:
Réponses:
Héritage. La liste a été initialement définie pour ressembler à des langages fonctionnels:
Bien sûr, Scala a fait évoluer d'autres collections, de manière ponctuelle. Lorsque 2.8 est sorti, les collections ont été redessinés pour une réutilisation du code et l' API cohérente, de sorte que vous pouvez utiliser
++
pour concaténer les deux collections - et même itérateurs. List, cependant, a réussi à conserver ses opérateurs d'origine, à l'exception d'un ou deux qui se sont dépréciés.la source
:::
en faveur de++
maintenant? Utilisez également+:
au lieu de::
?::
est utile en raison de la correspondance de motifs (voir le deuxième exemple de Daniel). Vous ne pouvez pas faire ça avec+:
List
au lieu deSeq
, vous pourriez aussi bien utiliser desList
méthodes idiomatiques . D'un autre côté, il sera plus difficile de passer à un autre type, si vous le souhaitez.::
et:::
) et des opérations plus générales qui sont communes à d'autres collections. Je ne laisserais tomber aucune des opérations de la langue.:+
et+:
extracteurs d'objet.Utilisez toujours
:::
. Il y a deux raisons: l'efficacité et la sécurité du type.Efficacité
x ::: y ::: z
est plus rapide quex ++ y ++ z
, parce que:::
c'est juste associatif.x ::: y ::: z
est analysé commex ::: (y ::: z)
, ce qui est algorithmiquement plus rapide que(x ::: y) ::: z
(ce dernier nécessite O (| x |) étapes supplémentaires).Type de sécurité
Avec
:::
vous ne pouvez concaténer que deuxList
s. Avec++
vous pouvez ajouter n'importe quelle collectionList
, ce qui est terrible:++
est également facile à mélanger avec+
:la source
x ::: y ::: z
devrait être remplacé parList(x, y, z).flatten
. pastebin.com/gkx7Hpadx
ety
(z
n'est jamais itérée dans tous les cas, donc n'a aucun effet sur le temps d'exécution, c'est pourquoi il est préférable d'ajouter une longue liste à une courte que l'inverse) mais la complexité asymptotique ne raconte pas toute l'histoire.x ::: (y ::: z)
itèrey
et ajoutez
, puis itèrex
et ajoute le résultat dey ::: z
.x
ety
sont tous deux répétés une fois.(x ::: y) ::: z
itèrex
et ajoutey
, puis itère le résultat dex ::: y
et ajoutez
.y
est toujours itéré une fois maisx
est itéré deux fois dans ce cas.:::
ne fonctionne qu'avec des listes, alors qu'il++
peut être utilisé avec n'importe quel traversable. Dans l'implémentation actuelle (2.9.0),++
retombe:::
si l'argument est également aList
.la source
Un autre point est que la première phrase est analysée comme suit:
Alors que le deuxième exemple est analysé comme suit:
Donc, si vous utilisez des macros, vous devez faire attention.
En outre,
++
pour deux listes appelle:::
mais avec plus de surcharge car cela demande une valeur implicite pour avoir un générateur de List en List. Mais les microbenchmarks n'ont rien prouvé d'utile dans ce sens, je suppose que le compilateur optimise de tels appels.Micro-repères après échauffement.
Comme l'a dit Daniel C. Sobrai, vous pouvez ajouter le contenu de n'importe quelle collection à une liste en utilisant
++
, alors qu'avec:::
vous, vous ne pouvez concaténer que des listes.la source