我知道我可以在Common Lisp中执行以下操作:
CL-USER> (let ((my-list nil))
(dotimes (i 5)
(setf my-list (cons i my-list)))
my-list)
(4 3 2 1 0)
Run Code Online (Sandbox Code Playgroud)
我怎么在Clojure中这样做?特别是,如果没有Clojure中的setf,我该怎么做呢?
我在Common Lisp中所做的个人翻译将是Clojurewise:
(into (list) (range 5))
Run Code Online (Sandbox Code Playgroud)
这导致:
(4 3 2 1 0)
Run Code Online (Sandbox Code Playgroud)
一点解释:
该函数将into所有元素连接到一个集合,这里是一个新列表,使用(list)其他集合创建,这里是范围0 .. 4.conj每个数据结构的行为不同.对于列表,conj行为如下cons:它将一个元素放在列表的头部并将其作为新列表返回.那么这是做什么的:
(cons 4 (cons 3 (cons 2 (cons 1 (cons 0 (list))))))
Run Code Online (Sandbox Code Playgroud)
这与您在Common Lisp中所做的类似.Clojure的不同之处在于我们一直在返回新的列表,而不是改变一个列表.只有在Clojure中真正需要时才会使用变异.
当然你也可以马上得到这个列表,但这可能不是你想知道的:
(range 4 -1 -1)
Run Code Online (Sandbox Code Playgroud)
要么
(reverse (range 5))
Run Code Online (Sandbox Code Playgroud)
或者......我能提出的最短版本:
'(4 3 2 1 0)
Run Code Online (Sandbox Code Playgroud)
;-).
在Clojure中做到这一点的方法是不要这样做:Clojure讨厌可变状态(它是可用的,但不鼓励使用它用于每一件小事).相反,请注意模式:你真的在计算(cons 4 (cons 3 (cons 2 (cons 1 (cons 0 nil))))).这看起来非常像减少(如果你愿意,还可以折叠).那么,(reduce (fn [acc x] (cons x acc)) nil (range 5))这就产生了你想要的答案.
| 归档时间: |
|
| 查看次数: |
1271 次 |
| 最近记录: |