Пусть против связывания в Clojure - PullRequest
68 голосов
/ 06 октября 2009

Я понимаю, что они разные, так как один работает для установки *compile-path*, а другой нет. Тем не менее, мне нужна помощь, почему они разные.

let создает новую область с заданными привязками, но binding ...?

Ответы [ 3 ]

106 голосов
/ 06 октября 2009

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 .

12 голосов
/ 11 ноября 2010

Еще одно синтаксическое отличие для let против привязки:

Для привязки все начальные значения оцениваются до того, как какое-либо из них будет привязано к переменным. Это отличается от 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
9 голосов
/ 06 октября 2009

binding привязывает значение к имени в глобальной среде для потока

Как вы упомянули, let создает новую область для указанных привязок.

...