Scala liste de concaténation, ::: vs ++
Quelle est la différence entre :::
et ++
pour la concaténation de listes de 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
De la documentation il ressemble ++
est plus général, alors que :::
est List
spécifiques. Est le dernier parce qu'il est utilisé dans d'autres langages fonctionnels?
- Aussi
:::
est un préfixe de l'opérateur, comme toutes les méthodes commençant par:
- Les réponses assez bien délimiter le chemin que la scala a évolué dans des listes et de l'exploitant de l'homogénéité dans la Scala (ou l'absence de celui-ci). C'est un peu malheureux que quelque chose de si simple a une longue queue de minuties à confondre et à perdre le temps de tout Scala de l'apprenant. J'aimerais que ce soit stabilisé en 2.12.
InformationsquelleAutor Luigi a.k.a. Rhys | 2011-07-02
Vous devez vous connecter pour publier un commentaire.
Héritage. La liste a été défini à l'origine pour être fonctionnelle-langues-recherche:
Bien sûr, Scala évolué autres collections, d'une manière ad-hoc. Lorsque 2.8 est sorti, les collections ont été redessinés pour un maximum de réutilisation de code et d'API cohérente, de sorte que vous pouvez utiliser
++
pour concaténer tout deux collections -- et même les itérateurs. Liste, cependant, obtenu de garder son origine opérateurs, à part un ou deux qui s'est obsolète.:::
en faveur de++
maintenant? Également utiliser+:
au lieu de::
?::
est utile en raison de filtrage (voir Daniel deuxième exemple). Vous ne pouvez pas le faire avec+:
+:
et:+
comme objet d'extracteurs.List
au lieu deSeq
, vous pourriez aussi bien utiliser idiomatiquesList
méthodes. D'autre part, il sera plus difficile de modifier d'un autre type, si jamais vous avez envie de le faire.::
et:::
) et le fonctionnement plus général qui sont communs à d'autres collections. Je ne voudrais pas tomber, soit le fonctionnement de la langue.:+
et+:
objet d'extracteurs.++
être obsolète?::
et:::
est qu'ils sontList
-seulement, comme les autres langues qui en ont. Si vous n'êtes pas venu par le biais de ces langues, il n'aura pas de sens pour vous, ce qui ne signifie pas qu'il est dénué de sens.::
dans la correspondance de motif. Mais est-ce que toute la pertinence de la méthode::
? Pour des raisons de cohérence, elles sont définies de la même façon, mais ils pourraient ajouter le support pour+:
et:+
dans la correspondance de modèle droit?? Est-ce ce 0__'s point?+:
dans la correspondance de motif. Il n'y a pas de raison d'utiliser::
, dans la correspondance de motif ou d'ailleurs, à l'exception d'une esthétique de préférence, si vous en avez un.:::
ne fonctionne qu'avec des listes, alors que++
peut être utilisé avec n'importe quel traversable. Dans l'implémentation actuelle (2.9.0),++
retombe sur:::
si l'argument est aussi unList
.Toujours utiliser
:::
. Il y a deux raisons: l'efficacité et la sécurité de type.Efficacité
x ::: y ::: z
est plus rapide quex ++ y ++ z
, parce que:::
est droit associatif.x ::: y ::: z
est analysée commex ::: (y ::: z)
, qui est algorithmiquement plus vite que(x ::: y) ::: z
(ce dernier nécessite O(|x|) plus).De sécurité de Type
Avec
:::
vous ne pouvez concaténer deuxList
s. Avec++
vous pouvez ajouter n'importe quelle collection deList
, ce qui est terrible:++
est également facile à mélanger avec+
:x ::: y ::: z
doit être remplacé parList(x, y, z).flatten
. pastebin.com/gkx7HpadList(1) ::: List("2")
devientList[Any] = List(1, 2)
. Si le type de la sécurité est une préoccupation(comme il devrait l'être), je vous recommande d'éviter à la fois++
et:::
en faveur de scalaz de|+|
ou similaire. Si l'efficacité est la principale préoccupation, puis par tous les moyens l'utilisation:::
:::
et++
utiliser le même concept avecListBuffer
sous le capot et deux d'entre eux doivent avoir le même temps de la complexité -O(n)
où n = x + y + z, si je me trompe, s'il vous plaît, corrigez-moi.x ::: (y ::: z)
et(x ::: y) ::: z
vigueur à l'itération le long de toutes les listes -x, y, z
mais dans un ordre différent.x ::: (y ::: z)
doit itérer y et z et en fin de compte x, tandis que(x ::: y) ::: z
- x et y et enfin z. Et algorithmiquement dans les deux cas, ilO(n) n = x+y+z
x
ety
(z
n'est jamais réitéré, en tout cas, n'a aucune influence sur le temps d'exécution, c'est pourquoi il est préférable d'ajouter une longue liste pour une courte durée, que l'inverse), mais la complexité asymptotique ne pas raconter toute l'histoire.x ::: (y ::: z)
itèrey
et ajoutez
, puis itèrex
et ajoute le résultat dey ::: z
.x
ety
sont à la fois réitéré une fois.(x ::: y) ::: z
itèrex
et ajoutey
, puis itère le résultat dex ::: y
et ajoutez
.y
est encore réitéré une fois, maisx
est répété deux fois dans ce cas.Un autre point est que la première phrase est analysée comme:
Alors que le deuxième exemple est analysé comme:
Donc, si vous utilisez des macros, vous devez prendre soin de.
En outre,
++
pour les deux listes appelle:::
mais avec plus de surcharge, car il demande une valeur implicite de disposer d'un générateur de Liste de Liste. Mais microbenchmarks n'a pas à prouver quoi que ce soit d'utile dans ce sens, je suppose que le compilateur optimise de tels appels.Micro-Benchmarks après l'échauffement.
Comme Daniel C. Sobrai dit, vous pouvez ajouter le contenu de n'importe quelle collection d'une liste à l'aide de
++
, alors qu'avec:::
vous ne pouvez concaténer des listes.