首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure中的setf

Clojure中的setf
EN

Stack Overflow用户
提问于 2011-12-17 06:26:38
回答 6查看 1.5K关注 0票数 2

我知道我可以用Common Lisp做以下事情:

代码语言:javascript
复制
CL-USER> (let ((my-list nil))
       (dotimes (i 5)
         (setf my-list (cons i my-list)))
       my-list)
(4 3 2 1 0)

我如何在Clojure中做到这一点?具体地说,在没有Clojure中的setf的情况下,我如何做到这一点?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-12-20 00:10:53

出于线程安全的考虑,Clojure禁止局部变量的突变,但即使没有突变,也仍然可以编写循环。在循环的每次运行中,您都希望my-list具有不同的值,但这也可以通过递归来实现:

代码语言:javascript
复制
(let [step (fn [i my-list]
             (if (< i 5)
               my-list
               (recur (inc i) (cons i my-list))))]
  (step 0 nil))

Clojure也有一种方法可以“只做循环”,而不需要创建一个新函数,即loop。它看起来像一个let,但您也可以跳到其主体的开头,更新绑定,然后使用recur再次运行主体。

代码语言:javascript
复制
(loop [i 0
       my-list nil]
  (if (< i 5)
    my-list
    (recur (inc i) (cons i my-list))))

使用递归尾部调用“更新”参数看起来非常类似于更改变量,但有一个重要的区别:当您在Clojure代码中键入my-list时,其含义始终为my-list的值。如果嵌套函数在my-list上关闭,并且循环继续到下一次迭代,则嵌套函数将始终看到创建嵌套函数时my-list具有的值。局部变量总是可以替换为它的值,在进行递归调用之后,您拥有的变量在某种意义上是一个不同的变量。

( Clojure编译器执行优化,以便这个“新变量”不需要额外的空间:当需要记住一个变量时,它的值将被复制;当调用recur时,旧变量将被重用。)

票数 3
EN

Stack Overflow用户

发布于 2011-12-17 19:32:02

我个人对你在Common Lisp中所做的事情的翻译是:

代码语言:javascript
复制
(into (list) (range 5))

这会导致:

代码语言:javascript
复制
(4 3 2 1 0)

一个小小的解释:

函数into将所有元素连接到一个集合,这里是一个用(list)创建的新列表,来自其他集合,这里是范围0 .. 4conj的行为因数据结构而异。对于列表,conj的行为类似于cons:它将一个元素放在列表的头部,并将其作为新列表返回。所以它做的是这样的:

代码语言:javascript
复制
(cons 4 (cons 3 (cons 2 (cons 1 (cons 0 (list))))))

这与您在Common Lisp中所做的类似。Clojure的不同之处在于,我们总是返回新的列表,而不是更改一个列表。在Clojure中,只有在真正需要的时候才会使用突变。

当然,你也可以马上得到这个列表,但这可能不是你想知道的:

代码语言:javascript
复制
(range 4 -1 -1)

代码语言:javascript
复制
(reverse (range 5))

或者..。我能想到的最短版本是:

代码语言:javascript
复制
'(4 3 2 1 0)

;-)。

票数 8
EN

Stack Overflow用户

发布于 2011-12-17 08:09:10

尽管在Clojure中这样做的方法是不这样做: Clojure讨厌可变状态(它是可用的,但不鼓励在每一件小事上使用它)。相反,请注意模式:您实际上是在计算(cons 4 (cons 3 (cons 2 (cons 1 (cons 0 nil)))))。这看起来非常像reduce (如果你喜欢,也可以是fold )。所以,(reduce (fn [acc x] (cons x acc)) nil (range 5)),它产生了你想要的答案。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8540855

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档