Odpowiedzi:
Po raz kolejny wydaje mi się, że odpowiedziałem na swoje pytanie, zniecierpliwiony i zadając je na #clojure na Freenode. Zachęcamy do odpowiadania na własne pytania na Stackoverflow.com: D
Odbyłem szybką dyskusję z Rich Hickey i oto jej sedno.
[12:21] <Raynes> Vectors aren't seqs, right?
[12:21] <rhickey> Raynes: no, but they are sequential
[12:21] <rhickey> ,(sequential? [1 2 3])
[12:21] <clojurebot> true
[12:22] <Raynes> When would you want to use a list over a vector?
[12:22] <rhickey> when generating code, when generating back-to-front
[12:23] <rhickey> not too often in Clojure
Jeśli dużo zajmowałeś się programowaniem w Javie i znasz strukturę kolekcji Java, pomyśl o listach, takich jak LinkedList
i wektorach, takich jak ArrayList
. Możesz więc wybrać pojemniki w ten sam sposób.
Dla dalszego wyjaśnienia: jeśli zamierzasz dodawać elementy pojedynczo na początku lub na końcu sekwencji, lista połączona jest znacznie lepsza niż wektor, ponieważ elementy nie muszą być tasowane za każdym razem. Jeśli jednak chcesz często uzyskiwać dostęp do określonych elementów (nie blisko początku ani z tyłu listy) (tj. Dostęp losowy), będziesz chciał użyć wektora.
Nawiasem mówiąc, wektory można łatwo przekształcić w sekwencje.
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)
ArrayList
bez efektywnego ponownego zaimplementowania ArrayDeque
siebie.
Wektory mają O (1) czasów dostępu swobodnego, ale muszą być wstępnie przydzielone. Listy można rozszerzać dynamicznie, ale dostęp do elementu losowego jest O (n).
Kiedy używać wektora:
Kiedy używać listy:
~O(1)
, dla tych, dla których to wyjaśnienie kosztów może być pomocne - stackoverflow.com/questions/200384/constant-amortized-time
tylko krótka uwaga dodatkowa:
„Czytałem, że wektory nie są sekwencjami, ale listy są”.
sekwencje są bardziej ogólne niż listy lub wektory (lub mapy lub zbiory).
Szkoda, że REPL drukuje listy i sekwencje w ten sam sposób, ponieważ naprawdę sprawia, że wygląda na to, że listy są sekwencjami, mimo że są różne. funkcja (seq) utworzy sekwencję z wielu różnych rzeczy, w tym list, a następnie możesz przekazać tę sekwencję do dowolnej z wielu funkcji, które wykonują sprytne rzeczy z sekwencjami.
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 ma skrót, który zwraca swój argument, jeśli jest już sekwencją:
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);
}
listy są sekwencjami, chociaż inne rzeczy też są i nie wszystkie sekwencje są listami.
class
zamiast class?
?
clojure.lang.PersistentList
do mnie. Zakładam, że miałeś zamiar class
nie pisać class?
.
class
zwraca tę samą PersistentList dla obu wymienionych przez Ciebie wyrażeń, oznacza to, że sekwencje i listy są rzeczywiście tym samym?