Я читал, что векторы не являются секциями, но являются списками. Я не уверен, в чем смысл использования одного над другим. Кажется, что векторы используются больше всего, но есть ли причина для этого?
В Clojure, когда я должен использовать вектор над списком и наоборот?
Ответ 1
Еще раз, кажется, я ответил на свой вопрос, вызвав нетерпение и попросив его в # clojure на Freenode. Хорошая вещь, отвечающая на ваши вопросы, рекомендуется на Stackoverflow.com: D
У меня было быстрое обсуждение с Ричем Хики, и вот суть этого.
[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
Ответ 2
Если вы много программировали на Java и знакомы с каркасом Java-коллекции, подумайте о таких списках, как LinkedList
и таких векторах, как ArrayList
. Таким образом, вы можете выбирать контейнеры одинаково.
Для дальнейшего уточнения: если вы намерены добавлять элементы отдельно к фронту или задней части последовательности, связанный список намного лучше, чем вектор, потому что элементы не нужно перетасовывать каждый раз. Однако, если вы хотите часто использовать определенные элементы (не рядом с передним или задним списком) (т.е. Произвольный доступ), вам понадобится использовать вектор.
Кстати, векторы легко превращаются в 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)
Ответ 3
Векторы имеют O (1) случайное время доступа, но они должны быть предварительно распределены. Списки могут быть динамически расширены, но доступ к случайному элементу - O (n).
Ответ 4
Когда использовать вектор:
- Индексированная производительность доступа - вы получаете ~ O (1) стоимость индексированного доступа против O (n) для списков
- Добавление - с conj является ~ O (1)
- Удобная нотация - мне легче набирать и читать [1 2 3], чем "(1 2 3)" для литерального списка в тех случаях, когда они будут работать.
Когда использовать список:
- Если вы хотите получить к нему доступ в виде последовательности (поскольку списки напрямую поддерживают seq без необходимости размещения новых объектов)
- Prepending - добавление к началу списка с минусами или предпочтительно conj является O (1)
Ответ 5
просто краткое примечание:
"I read that Vectors are not seqs, but Lists are."
последовательности более общие, чем списки или векторы (или карты или наборы).
Несчастливо, что REPL печатает списки и последовательности одного и того же, потому что это действительно делает его похожим на списки - это последовательности, даже если они разные. функция (seq) будет создавать последовательность из множества разных вещей, включая списки, и вы можете затем передать этот фрагмент любому из множества функций, которые делают изящные вещи с помощью 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 имеет ярлык, который возвращает свой аргумент, если он уже является 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);
}
списки - это последовательности, хотя есть и другие вещи, а не все последовательности - это списки.