3

看起来 clojurelet是顺序的,并且对应于一个 scheme let*。clojure 是否具有像 scheme's 这样的非顺序绑定机制let

4

3 回答 3

4

我相信binding宏是并行的而不是顺序的。

请参阅:http ://clojuredocs.org/clojure_core/clojure.core/binding

于 2012-08-07T19:59:02.823 回答
2

letfn 是一种函数的并行绑定形式,允许人们编写相互递归的局部函数。尽管它可以在紧要关头使用,但它并不像您所寻求的那样通用。

user> (letfn [(a [] 4) 
              (b [] c) 
              (c [] a)] 
       (a))
4

只要您将值分配给 vars 中的事物并想要动态范围,就可以使用绑定

user> (def ^:dynamic x 4)
#'user/x
user> (defn foo [] x)
#'user/foo
user> (binding [x 8] (+ x (foo)))
16 ; the value of x that gets called by foo is modified by the caller
   ; yielding 16 instead of 12

user> (binding [x 8 a 7] (+ x (foo)))
; Evaluation aborted.
Unable to resolve var: a in this context

如果您尝试使用并行绑定,则动态作用域将给出与方案中的 let* 不同的结果

user> (def ^:dynamic a 2)
#'user/a
user> (binding [x 8 a 7] (+ x a))
15
user> (binding [x 8 a (+ x 2)] (+ x a))
14 ; this would be 18 if the binding of x to 8 had been used
   ; instead the root value of 4 was used.

一般来说,let如果需要,最常见的是顺序绑定或使用嵌套 s。

于 2012-08-07T20:27:00.480 回答
0

binding不会为您提供与并行相同的功能,let因为它取决于绑定的存在。如上所述letfn,只要您不介意将值包装在函数中,它就会起作用。另一种解决方案是使用宏编写并行 let:

(defmacro letp 
  [bindings & exprs]
  (let [bindings (partition 2 bindings)
        vars     (->> bindings (map first) vec)
        values   (->> bindings (map second))]
    `((fn ~vars ~@exprs)
      ~@values)))

所以以下成立:

(def a 7)

(letp [a 5 b a] b)
;;=> 7
于 2012-08-08T01:46:27.007 回答