2009-10-06 4 views
65

*compile-path*을 설정하기 때문에 다른 것이므로 하나는 이해하지 못합니다. 그러나, 나는 그들이 왜 다른지에 대한 도움이 필요합니다.Clojure에서 Let vs. Binding을 작성하십시오.

let은 지정된 바인딩을 사용하여 새 범위를 만듭니다. 그러나 binding ...?

답변

99

let은 일부 값에 대해 어휘 적으로 범위가 지정되지 않은 변경할 수없는 별칭을 만듭니다. bindingVar에 대해 동적 범위가 지정된 바인딩을 만듭니다.

동적 바인딩은 binding 양식의 코드와 해당 코드가 호출하는 모든 코드 (로컬 어휘 범위가 아닌 경우에도)가 새 바인딩을 볼 수 있음을 의미합니다.

을 감안할 때 : 그것은에서 작동하기 때문에

user> (binding [x 1] (var-get #'x)) 
1 
user> (let [x 1] (var-get #'x)) 
0 

binding이 (자격을 갖춘 이름을 사용할 수 있습니다 :

user> (def ^:dynamic x 0) 
#'user/x 

binding 실제로 단지 로컬 별명을 가진 VAR ​​그림자 Var하지만 let 바인딩 동적를 생성 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 -introduced 바인딩은 스레드 로컬로 변경할 수 있습니다 : 동적 바인딩 대

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 참조하십시오. 바인딩 대하자에 대한

+4

이 플러스 http://en.wikipedia.org/wiki/Scope_(programming)#Static_versus_dynamic_scoping은 내 이해를 향상 시켰습니다. 감사합니다! – Carl

+0

x는 오류가 발생하지 않도록^: 동적 힌트로 바인딩되어야합니다. – WeGi

8

binding는 스레드 별 지구 환경

당신이 언급 한 바와 같이, let 말했다 바인딩을위한 새로운 범위를 생성에 이름에 값을 바인딩합니다.

10

또 하나 개의 문법 차이 : 그 중 하나가 바르에 결합되기 전에 바인딩에 대한

모든 초기 값이 평가됩니다. 이것은 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 
+0

두 번째 예제가 작동하도록하려면^: dynamic이 x를 0 (동적으로)으로 정의해야합니다. – John