Dans Clojure, quand dois-je utiliser un vecteur sur une liste et inversement?

J’ai lu que les vecteurs ne sont pas des seqs, mais les listes sont. Je ne suis pas certain de la raison d’être de l’utilisation l’une de l’autre. Il semble que les vecteurs soient les plus utilisés, mais y a-t-il une raison à cela?

    Encore une fois, il semble que j’ai répondu à ma propre question en m’impatientant et en le posant dans #clojure sur Freenode. La bonne chose à répondre à vos propres questions est encouragée sur Stackoverflow.com: D

    J’ai eu une brève discussion avec Rich Hickey, et voici l’essentiel.

    [12:21]  Vectors aren't seqs, right? [12:21]  Raynes: no, but they are sequential [12:21]  ,(sequential? [1 2 3]) [12:21]  true [12:22]  When would you want to use a list over a vector? [12:22]  when generating code, when generating back-to-front [12:23]  not too often in Clojure 

    Si vous avez beaucoup programmé Java et que vous connaissez le framework de collecte Java, pensez à des listes comme LinkedList et à des vecteurs comme ArrayList . Vous pouvez donc choisir les conteneurs de la même manière.

    Pour plus de précisions: si vous avez l’intention d’append des éléments individuellement au recto ou au verso de la séquence, une liste chaînée est bien meilleure qu’un vecteur, car les éléments n’ont pas besoin d’être mélangés à chaque fois. Cependant, si vous voulez obtenir fréquemment des éléments spécifiques (pas près de l’avant ou de l’arrière de la liste) (c.-à-d. Accès aléatoire), vous voudrez utiliser le vecteur.

    En passant, les vecteurs peuvent facilement être transformés en seqs.

     user=> (def v (vector 1 2 3)) #'user/v user=> v [1 2 3] user=> (seq v) (1 2 3) user=> (rseq v) (3 2 1) 

    Les vecteurs ont un temps d’access aléatoire de O (1), mais ils doivent être préalloués. Les listes peuvent être étendues dynamicment, mais l’access à un élément aléatoire est O (n).

    Quand utiliser un vecteur:

    • Performances d’access indexé – Vous obtenez ~ O (1) coût pour l’access indexé par rapport à O (n) pour les listes
    • Ajout – avec conj est ~ O (1)
    • Notation commode – Je trouve à la fois plus facile de taper et de lire [1 2 3] que ‘(1 2 3) pour une liste littérale dans les cas où l’une ou l’autre fonctionnerait.

    Quand utiliser une liste:

    • Lorsque vous voulez y accéder en tant que séquence (puisque les listes supportent directement seq sans avoir à allouer de nouveaux objects)
    • Pré-réglage – append au début d’une liste avec contre ou de préférence conjonction est O (1)

    juste une note rapide:

      "J'ai lu que les vecteurs ne sont pas des seqs, mais les listes sont." 

    les séquences sont plus génériques que les listes ou les vecteurs (ou les cartes ou les ensembles).
    Il est regrettable que le REPL imprime les listes et les séquences de la même manière, car cela donne vraiment l’impression que les listes sont des séquences même si elles sont différentes. La fonction (seq) va créer une séquence à partir de beaucoup de choses différentes, y compris des listes, et vous pouvez ensuite alimenter cette séquence à la pléthore de fonctions qui font des choses astucieuses avec les seqs.

     user> (class (list 1 2 3)) clojure.lang.PersistentList user> (class (seq (list 1 2 3))) clojure.lang.PersistentList user> (class (seq [1 2 3])) clojure.lang.PersistentVector$ChunkedSeq 

    Sec a un raccourci qui renvoie son argument s’il s’agit déjà d’un seq:

     user> (let [alist (list 1 2 3)] (identical? alist (seq alist))) true user> (identical? (list 1 2 3) (seq (list 1 2 3))) false static public ISeq seq(Object coll){ if(coll instanceof ASeq) return (ASeq) coll; else if(coll instanceof LazySeq) return ((LazySeq) coll).seq(); else return seqFrom(coll); } 

    les listes sont des séquences, bien que d’autres choses le soient aussi, et toutes les séquences ne sont pas des listes.