通过let绑定进行Clojure递归

时间:2014-01-06 07:08:08

标签: recursion clojure let

来自core.clj,assoc的定义(修剪元数据等)

(def assoc
 (fn assoc
   ([map key val] (. clojure.lang.RT (assoc map key val)))
   ([map key val & kvs]
    (let [ret (assoc map key val)]
      (if kvs
        (if (next kvs)
          (recur ret (first kvs) (second kvs) (nnext kvs))
          (throw (IllegalArgumentException. "assoc expects even no of args...")))
    ret)))))

ret的let绑定实现了什么?为什么不只是:

(def assoc
 (fn assoc
   ([map key val] (. clojure.lang.RT (assoc map key val)))
   ([map key val & kvs]
      (if kvs
        (if (next kvs)
          (recur (first kvs) (second kvs) (nnext kvs))
          (throw (IllegalArgumentException. "assoc expects even no of args...")))
    ret))))

基本测试(在ClojureCLR中)似乎表明后者工作正常,我找不到任何说明前者使用的文件。有线索吗?

谢谢,加里

1 个答案:

答案 0 :(得分:2)

您的版本应该无法编译,因为没有足够的参数传递给recur(在这种情况下需要四个)。存在let以将传递给第一个主体(3-arity)的第一对键/值的关联结果绑定为ret。如果先使用recur kvs = nil使用nnext自行调用第二个正文(因为recur表单中的(if kvs ..)为第四个参数)ret将失败,并且可以简单地返回kvs。如果可能发生更多{{1}}尾递归。