web-dev-qa-db-ja.com

Clojureでは、リストに対してベクトルを使用する必要があるのはいつですか?

ベクターはシーケンスではなく、リストがシーケンスであると読みました。どちらを使用するのか、理由はわかりません。ベクトルが最も使用されているようですが、その理由はありますか?

140
Rayne

ここでも、Freenodeの#clojureでせっかちになって質問することで、自分の質問に答えたようです。 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
109
Rayne

Javaプログラミングをたくさん行い、Javaコレクションフレームワークに精通している場合、LinkedListなどのリスト、およびベクトルを考えてください。 ArrayListのように、同じ方法でコンテナを選択できます。

さらに明確にするために、アイテムをシーケンスの前面または背面に個別に追加する場合、アイテムを毎回シャッフルする必要がないため、リンクリストはベクターよりもはるかに優れています。ただし、特定の要素(リストの前後近くではない)を頻繁に取得する(つまり、ランダムアクセス)場合は、vectorを使用します。

ところで、ベクトルは簡単にシーケンスに変換できます。

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)
83

ベクターにはO(1)ランダムアクセス時間がありますが、事前に割り当てる必要があります。リストは動的に拡張できますが、ランダム要素へのアクセスはO(n)です。

39
Svante

ベクトルを使用する場合:

  • インデックス付きアクセスのパフォーマンス-インデックス付きアクセスに対して〜O(1)のコストと、リストのO(n)
  • 追加-conjで〜O(1)
  • 便利な表記法-どちらかが機能する状況では、リテラルリストの '(1 2 3)よりも[1 2 3]と入力する方が簡単です。

リストを使用する場合:

  • シーケンスとしてアクセスしたい場合(リストは新しいオブジェクトを割り当てることなくseqを直接サポートするため)
  • プリペンディング-consまたはできればconjでリストの先頭に追加するとO(1)
28
mikera

ちょっとしたメモ:

「ベクターはシーケンスではありませんが、リストはシーケンスであると読みました。」 

シーケンスは、リストやベクター(またはマップやセット)よりも一般的です。
それは残念です REPLは同じリストとシーケンスを出力します たとえリストが異なっていても、リストがシーケンスのように見えるためです。 (seq)関数は、リストを含む多くの異なるものからシーケンスを作成します。その後、その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);
}

リストはシーケンスですが、他のものも同様ですが、すべてのシーケンスがリストではありません。

13
Arthur Ulfeldt