2017-08-05 43 views
3

我想要一个原子中的Clojure矢量来模拟一个有状态的FIFO(推到底,从头开始弹出)。试图Clojure原子将矢量转换为列表?

(def stack (atom [])) 

然后push如下:

(swap! stack #(conj % 1)) 
(swap! stack #(conj % 2)) 

期待

[1 2] 

但得到

(2 1) 

没什么大不了的,它只是意味着我必须扭转( O(n))的值原子(持久性列表)以按顺序获取项目的顺序(例如,按顺序将命令性命令流送到虚拟机)。尽管如此,这是一个惊喜。

是否有clojure.core FIFO我可以打包成一个原子?我想到了priority-map,但它似乎矫枉过正。关于clojuredocs.org上的swap!的示例使用列表或地图,但不是我想要的。我发现了很多搜索“FIFO Clojure”的样本,但有些样本有点丰富,例如clojure.core.cache(类似地图而不是向量样); amalloy的环形缓冲区(外部依赖)。寻找真正小而直接的东西。我没有在StackOverflow的自动建议中看到答案。

回答

5

东西是不完全正确的代码的大背景;我假设你比你发布的例子还有更多的事情要做?

这里的结果在我的REPL和我所期望的:

user=> (def stack (atom [])) 
#'user/stack 
user=> (swap! stack #(conj % 1)) 
[1] 
user=> (swap! stack #(conj % 2)) 
[1 2] 
user=> @stack 
[1 2] 

当使用载体,项目被添加到集合的末尾。如果stack只是一个列表,您看到的结果看起来就像您会得到的行为,例如,添加到前面:

user=> (def stack (atom '())) 
#'user/stack 
user=> (swap! stack #(conj % 1)) 
(1) 
user=> (swap! stack #(conj % 2)) 
(2 1) 
user=> @stack 
(2 1) 

所以我想知道如果在你的代码的某个地方,你不知何故最终定义了一个列表,而不是一个向量。

+0

你说得对。调查。 –

+0

上下文是一堆重复测试推送和弹出。看起来像当我将最后一个项目从矢量堆栈中弹出时,原子剩下一个空列表而不是空矢量。后续将连接推到列表上而不是矢量。修复很容易在我的弹出功能中 - 如果最后一个弹出窗口清空堆栈,则放回空载体中。 –

+1

不,'(pop [1])'是'[]'。这不是你的问题。现在,如果你曾经调用过'rest',或者'seq',这可能会使它成为一个列表。 – amalloy