有没有办法改变Clojure中的参数?

Zch*_*yvr 3 clojure

在lisp中,我可以将参数传递给函数并在函数内进行更改.(AKA破坏性功能).但是,在Clojure中,我已经读过某个地方,在同一个函数中改变给定的参数是不允许的.例如:

(defn add-two-lists [list1 list2]
  (for [n (range (count list1))]
    (+ (nth list1 n) (nth list2 n))))
Run Code Online (Sandbox Code Playgroud)

这是一个普通函数,它的输出是两个相同列表的相加.但是,我想要这样的东西:

(defn add-two-lists [list1 list2 added_list]
  (set! added_list 
       (for [n (range (count list1))]  
          (+ (nth list1 n) (nth list2 n)))))
Run Code Online (Sandbox Code Playgroud)

也许我的使用set!是错误的或误用的,我仍然会得到错误.有没有一种优雅的方法来破坏性地修改Clojure中的参数?

mik*_*era 12

在Clojure中不鼓励进行破坏性修改 - 我鼓励您找到编写代码的方法,而无需借助破坏性更新.

本着给出Clojurey解决方案的精神,我会add-two-lists按如下方式编写您的函数:

(defn add-two-lists [list1 list2]
  (map + list1 list2))
Run Code Online (Sandbox Code Playgroud)

这有一些优点:

  • 它纯粹是功能性的
  • 这是懒惰的,所以你甚至可以添加无限长度的列表(尝试使用破坏性更新的参数!)
  • 它的性能是O(n),它是最优的 - 问题中的版本实际上是O(n ^ 2),因为nth它本身就是列表上的O(n)操作.
  • 它简洁明了:-)


Art*_*ldt 6

Clojure提供了几种在这种情况下运行良好的可变类型,例如,你可以传递atom给函数并让它在该atom中设置值.

(defn add-two-lists [list1 list2 added_list]
  (reset! added_list 
    (for [n (range (count list1))]  
       (+ (nth list1 n) (nth list2 n)))))
Run Code Online (Sandbox Code Playgroud)

然后在你调用它之后你用@/ deref edit 从原子中获取值:如果效率是目标,那么使用瞬态集合可能会有所帮助