Я понимаю, что они отличаются друг от друга, так как один работает для установки *compile-path*
, а другой нет. Однако мне нужна помощь в том, почему они разные.
let
создает новую область с данными привязками, но binding
...?
Я понимаю, что они отличаются друг от друга, так как один работает для установки *compile-path*
, а другой нет. Однако мне нужна помощь в том, почему они разные.
let
создает новую область с данными привязками, но binding
...?
let
создает для некоторого значения лексически измененный псевдоним. binding
создает привязку с динамической привязкой для некоторого Var
.
Динамическое связывание означает, что код внутри вашей формы binding
и любой код, который этот код вызывает (даже если не в локальной лексической области), увидит новое связывание.
Дано:
user> (def ^:dynamic x 0)
#'user/x
binding
фактически создает динамическое связывание для Var
, но let
только тень var с локальным псевдонимом:
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
Еще одна синтаксическая разница для let vs binding:
Для привязки все начальные значения вычисляются до того, как любой из них привязан к vars. Это отличается от let, где вы можете использовать значение предыдущего "псевдонима" в последующем определении.
user=>(let [x 1 y (+ x 1)] (println y))
2
nil
user=>(def y 0)
user=>(binding [x 1 y (+ x 1)] (println y))
1
nil
binding
связывает значение с именем в глобальной среде для каждого потока
Как вы уже упоминали, let
создает новую область для указанных привязок.