List 在Clojure中,什么时候应该在列表上使用向量,反之亦然?

List 在Clojure中,什么时候应该在列表上使用向量,反之亦然?,list,vector,clojure,sequences,List,Vector,Clojure,Sequences,我读到向量不是seq,而是列表。我不确定用一个代替另一个的理由是什么。向量似乎使用得最多,但这是有原因的吗?如果您已经做过很多Java编程,并且熟悉Java集合框架,请考虑像LinkedList这样的列表,以及像ArrayList这样的向量。所以你可以用同样的方法选择容器 进一步说明:如果您打算在序列的前面或后面单独添加项目,那么链表比向量要好得多,因为项目不需要每次都被洗牌。但是,如果您想频繁地(即随机访问)获取特定元素(不在列表的前面或后面),则需要使用vector 顺便说一下,向量可以很容

我读到向量不是seq,而是列表。我不确定用一个代替另一个的理由是什么。向量似乎使用得最多,但这是有原因的吗?

如果您已经做过很多Java编程,并且熟悉Java集合框架,请考虑像
LinkedList
这样的列表,以及像
ArrayList
这样的向量。所以你可以用同样的方法选择容器

进一步说明:如果您打算在序列的前面或后面单独添加项目,那么链表比向量要好得多,因为项目不需要每次都被洗牌。但是,如果您想频繁地(即随机访问)获取特定元素(不在列表的前面或后面),则需要使用vector

顺便说一下,向量可以很容易地转换为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)

向量有O(1)个随机访问时间,但它们必须预先分配。列表可以动态扩展,但访问随机元素是O(n)

再一次,我似乎不耐烦地在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
[12:21]向量不是序列,对吗?
[12:21]雷恩斯:没有,但它们是连续的
[12:21],(顺序?[1 2 3])
[12:21]没错
[12:22]您希望何时在向量上使用列表?
[12:22]生成代码时,从后向前生成
[12:23]在Clojure不太常见

只是一个简短的旁注:
"I read that Vectors are not seqs, but Lists are." 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);
}
列表是序列,尽管其他东西也是,但并非所有序列都是列表。

何时使用向量:

  • 索引访问性能-索引访问的成本为~O(1),而列表的成本为O(n)
  • 用conj追加-is~O(1)
  • 方便的表示法-我发现在任何一种情况下,文字列表的[1 2 3]都比“(1 2 3)更容易键入和阅读
何时使用列表:

  • 当您希望将其作为序列访问时(因为列表直接支持seq,而不必分配新对象)
  • 前置-将cons或conj添加到列表的开头,最好是O(1)


从技术上讲,如果您仅访问前面或后面的元素,则链表有O(1)个访问时间:-P然而,向量确实有O(1)个随机存取。:-)(“如上所述的链表”指的是双链表。单链表只能访问前面的元素。:-P)作为一个刚刚跳入Clojure的人,这是一个比其他两个有更多选票的更好的答案。另外两个没有任何用处。@ChrisJester-Young单链表如果存储对back元素的引用,就可以支持对back的O(1)访问。向量不是seqs,但它们是顺序的。(来源:Rich自己在#clojure在freenode上。)另外,我对Java一无所知,但Rich只是回答了我的问题。我将编辑我的帖子,说向量可以通过seq函数生成seq。:-)选择你的答案是因为它确实回答了问题,我真的不喜欢选择我自己的答案作为正确答案。似乎不对。谢谢。:)在添加第一个和最后一个的情况下,deque优于链表。这太可怕了:P@boxed如果不亲自重新实现
ArrayDeque
,则无法在向量或
ArrayList
上实现deque。当您在freenode上时,请来到黑暗面并加入#stackoverflow!:-PI实际上在那里闲着。我切换了IRC客户端,从未想过将#stackoverflow添加到我的自动连接列表中。我是一个Lisp新手,但我想知道向量、映射和集合是否以某种方式打破了所有代码都可以与数据互换的想法?或者这只是使Clojure成为一个实用的Lisp的因素之一?(或者,你能评估一个向量吗?)这是完全没有帮助的聊天片段。“生成代码”“从后面到前面生成”->的确切含义是??我真的很难回答这个问题,因为在我的书《懒惰+声明式风格=更好的性能》中,向量在Clojure中随处可见,这让我完全困惑。@Jimmyhoff我的理解是:“在宏中生成代码”=”(因为大多数代码是函数调用,因此是列表);“从前到后生成”=“通过预结束构建序列”。我的意思不是挑一个小问题,这只是一个指出一些有用的东西的机会。很多人已经知道了:)你不是说
class
而不是
class吗?
?不确定你的例子在clojure更新后是否发生了变化(我想我是在1.5版上),但你的两个例子都为我返回了
clojure.lang.PersistentList
。我想你是想写
class
而不是
class?
。我确实写了!我会解决这个问题,仍然有点困惑;由于
class
为您提到的这两个表达式返回相同的PersistentList,这意味着序列和列表实际上是完全相同的东西??即使在列表两端添加/删除列表也是一个非常糟糕的选择。deque要好得多(在CPU中,尤其是内存中)。对于那些成本解释可能会有所帮助的人,请尝试重新编写
~O(1)
-
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);
}