Вопрос

From core.clj, the definition of assoc (trimmed of metadata etc)

(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)))))

what does the let binding of ret achieve? Why is it not just:

(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))))

Rudimentary testing (in ClojureCLR) seemed to indicate the latter works ok, and I can't find any documentation indicating the use of the former. Any clues?

Thanks, gary

Это было полезно?

Решение

Your version should fail to compile because not enough arguments are passed to recur (four are needed in this case). The let exists to bind the result of association of the first pair of key/values passed to the first body (3-arity) as ret. In case the second body was invoked by itself earlier using recur with kvs = nil (as a result of calling nnext in the recur form as the fourth argument) (if kvs ..) will fail and ret can simply be returned. If there are more kvs tailrecursion can happen.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top