문제
설정을 위해 일하기 때문에 그들이 다르다는 것을 이해합니다. *compile-path*
그리고 하나는 아닙니다. 그러나 왜 다른지에 대한 도움이 필요합니다.
let
주어진 바인딩으로 새로운 범위를 만들지 만 binding
...?
해결책
let
일부 가치에 대해 어휘 스코프 링 불변의 별칭을 만듭니다. binding
일부는 동적으로 스코핑 된 바인딩을 만듭니다 Var
.
동적 바인딩은 내부의 코드를 의미합니다 binding
양식 및 해당 코드가 호출되는 모든 코드 (로컬 어휘 범위가 아닌 경우에도)는 새로운 바인딩을 볼 수 있습니다.
주어진:
user> (def ^:dynamic x 0)
#'user/x
binding
실제로 a에 대한 동적 바인딩을 만듭니다 Var
하지만 let
로컬 별칭으로 VAR을 그림자로 만 묘사합니다.
user> (binding [x 1] (var-get #'x))
1
user> (let [x 1] (var-get #'x))
0
binding
자격을 갖춘 이름을 사용할 수 있습니다 (작동하기 때문에 Var
모래 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 대 바인딩에 대한 하나의 구문 차이 :
바인딩의 경우, 모든 초기 값은 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
상기 바인딩에 대한 새로운 범위를 만듭니다.
제휴하지 않습니다 StackOverflow