Clojure中的定长堆栈结构

Clojure中的定长堆栈结构,clojure,queue,Clojure,Queue,固定长度堆栈(我最初称之为队列,但我想要的是堆栈)的最佳数据结构是什么?在固定长度堆栈中,项目被添加到前端,并且每次将项目添加到前端时,项目都会从末尾移除?不同长度的子向量也将从前端访问。我正在使用向量,现在考虑clojure.lang.PersistentQueue和手指树 编辑,澄清一下,类似于: > (def q (queue [1 2 3 4])) [1 2 3 4] > (push q 9 8 7) [7 8 9 1] > (peek (push q 9 8 7))

固定长度堆栈(我最初称之为队列,但我想要的是堆栈)的最佳数据结构是什么?在固定长度堆栈中,项目被添加到前端,并且每次将项目添加到前端时,项目都会从末尾移除?不同长度的子向量也将从前端访问。我正在使用向量,现在考虑clojure.lang.PersistentQueue和手指树

编辑,澄清一下,类似于:

> (def q (queue [1 2 3 4]))
[1 2 3 4]
> (push q 9 8 7)
[7 8 9 1]
> (peek (push q 9 8 7))
7
edit2:谢谢你迄今为止的所有答案,这已经变成了一个回到基础和阅读Clojure的乐趣的练习,例如学习subvec of subvec保留对第一个子向量的引用,而类似(vec(cons x(subvec…如果重复使用,将累加对所有中间子向量的引用。鉴于此,如何实现基于向量的队列的推送?:

(defn push [v i n] (if (>= (count v) n) (conj (subvec v 1 n) i) (conj v i) ) )

然后,可以通过rseq访问生成的向量,我认为rseq使用向量很快(因为它使用了索引偏移?

请查看位于IMO的Amalloy环形缓冲区,您可以使用以下列表:

(defn create-queue [len]
  (atom (repeat len nil)))

(defn push [queue new-items]
  (let [len (count @queue)
        len2 (count new-items)]
    (if (>= len2 len)
      (let [res (concat (take-last (- len2 len) new-items)
                        @queue)]
        (reset! queue (take len new-items))
        res)
      (let [res (take-last len2 @queue)]
        (reset! queue (concat new-items
                              (drop-last len2 @queue)))
        res))))
测试:


该死!通过链接到我的图书馆来窃取我的名誉?当然,我是开玩笑的。事实上,我很好奇你是怎么找到它的,因为我根本没有做广告,谷歌搜索
clojure ring buffer
也不容易找到任何东西。我在谷歌上找到了它,现在已经在我的书签中了;)。谢谢!很抱歉澄清,如果环缓冲区中的项目被添加并从前面偷看,然后从末尾弹出,则环缓冲区将是完美的。这与我在PersistentQueue中遇到的问题相同:conj添加到末尾但从前面偷看,但我只关心最近的项目(lifo)删除最旧的项目first@amalloy-我一直在尝试ring buffer,我注意到在源代码中,IPersistentCollection的一些函数是在IPersistentStack下提供的(空的和等效的),并且为IPersistentCollection提供的cons实现(第42行)似乎从未被调用过,就好像我调用过一样(cons x rb)使用环形缓冲区时,它会返回clojure.lang.Cons而不是代码所建议的环形缓冲区。这是为什么?
(Cons x anything)
总是返回一个Cons。java中的
Cons
方法是clojure中的
conj
函数。至于方法顺序,这些实现是否属于IPC或IPS并不重要,因为IPS扩展了IPC,因此继承了它的所有方法规范。通常将它们放在最特定的接口中,因为你不必输入那么多的接口名。好吧,但我已经在使用向量了。我看不出有必要在这里输入一个原子。我错过了你关于向量的问题的最后一句:)不,我们这里需要stm。此外,对于线程安全解决方案,我们需要ref而不是atom,并在dosync.hmm中完成所有工作,我更喜欢持久结构。哦,我刚刚注意到您更改了vectors的实现!我最初使用vectors,但后来发现subvec保留了对原始vector的引用,而不是gc'd,因此需要一个高效的持久队列(可能是我想要的堆栈?)
(def q (create-queue 4))

(take 4 @q)
-> (nil nil nil nil)
(push q [1 2 3])
-> (nil nil nil)
(take 4 @q)
-> (1 2 3 nil)
(push q [4 5])
-> (3 nil)
(take 4 @q)
-> (4 5 1 2)
(push q [6 7 8 9])
-> (4 5 1 2)
(take 4 @q)
-> (6 7 8 9)
(push q [10 11 12 13 15 16])
-> (15 16 6 7 8 9)
(take 4 @q)
-> (10 11 12 13)