Fixed Length Stack Structure in Clojure

What is the best data structure for a fixed-length stack (I originally called it a queue, but what I want is a stack), where the elements are added in front, and each time the element is added to the front element, the element is removed from the end? Different lengths of subvectors will also be available from the front. I used vectors, now I think about clojure.lang.PersistentQueue and finger trees.

change, clarify, something like:

> (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: thanks for all your answers so far, it has turned into an exercise to return to the basics and reading the Joy of Clojure, for example, learning that subvec subvec keeps a reference to the first subvec vector, while something like (vec ( cons x (subvec ... will be used if reused, it will reference all intermediate subselections. In light of this, how about this push implementation for a vector queue ?:

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

then the resulting vector could be obtained through rseq, which, in my opinion, is fast with vectors (due to the use of the offset index?)

+7
source share
2 answers

Look at the Amalloy ring buffer at https://github.com/amalloy/ring-buffer

+6
source

IMO you can only use a list:

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

Test:

 (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) 
+1
source

All Articles