159

ベクトルは seq ではなく、リストは seq であると読みました。どちらか一方を使用する理由が何であるかはわかりません。ベクターが一番使われているようですが、それには何か理由があるのでしょうか?

4

5 に答える 5

122

Once again, it seems I've answered my own question by getting impatient and asking it in #clojure on Freenode. Good thing answering your own questions is encouraged on Stackoverflow.com :D

I had a quick discussion with Rich Hickey, and here is the gist of it.

[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
于 2009-07-18T17:28:18.003 に答える
95

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

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

ところで、ベクトルは簡単に seq に変換できます。

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)
于 2009-07-18T17:06:45.537 に答える
46

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

于 2009-07-18T17:19:53.077 に答える
31

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

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

リストを使用する場合:

  • シーケンスとしてアクセスしたい場合 (リストは新しいオブジェクトを割り当てなくても直接 seq をサポートするため)
  • 先頭に追加 - cons またはできれば conj を使用してリストの先頭に追加すると、O(1) になります。
于 2011-11-24T14:58:02.170 に答える
14

簡単な補足:

「ベクトルは seq ではなく、リストは seq であると読みました。」

シーケンスは、リストまたはベクトル (またはマップまたはセット) よりも一般的です。
残念なことに、REPL がリストとシーケンスを同じように出力するのは、実際にはリストが異なっていてもリストがシーケンスのように見えるためです。(seq ) 関数は、リストを含むさまざまなものからシーケンスを作成し、その seq を、seq で気の利いたことを行う多数の関数のいずれかにフィードできます。

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);
}

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

于 2009-07-20T22:27:15.737 に答える