let
создает лексически ограниченный неизменяемый псевдоним для некоторого значения. binding
создает динамическую привязку для некоторого Var
.
Динамическое связывание означает, что код внутри формы binding
и любой код, который этот код вызывает (даже если не входит в локальную лексическую область), увидят новое связывание.
Дано:
user> (def ^:dynamic x 0)
#'user/x
binding
фактически создает динамическое связывание для Var
, но let
только затеняет переменную с локальным псевдонимом:
user> (binding [x 1] (var-get #'x))
1
user> (let [x 1] (var-get #'x))
0
binding
может использовать квалифицированные имена (поскольку он работает на Var
s), а let
не может:
user> (binding [user/x 1] (var-get #'x))
1
user> (let [user/x 1] (var-get #'x))
; Evaluation aborted.
;; Can't let qualified name: user/x
let
- введенные привязки не изменяемы. binding
-приведенные привязки являются локально изменяемыми:
user> (binding [x 1] (set! x 2) x)
2
user> (let [x 1] (set! x 2) x)
; Evaluation aborted.
;; Invalid assignment target
Лексическое и динамическое связывание:
user> (defn foo [] (println x))
#'user/foo
user> (binding [x 1] (foo))
1
nil
user> (let [x 1] (foo))
0
nil
См. Также Vars , let .