*compile-path*
と
*compile-path*
の設定には違いがあることを理解しています。しかし、私は彼らがなぜ違うのかについて助けが必要です。
let
は指定されたバインディングで新しいスコープを作成しますが、binding
...?
*compile-path*
と
*compile-path*
の設定には違いがあることを理解しています。しかし、私は彼らがなぜ違うのかについて助けが必要です。
let
は指定されたバインディングで新しいスコープを作成しますが、binding
...?
let
は、いくつかの値のレキシカルスコープ不変のエイリアスを作成します。 binding
は、一部のVar
の動的スコープ付きバインディングを作成します。
動的バインドとは、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
-introducedバインディングは変更可能ではありません。 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
binding
は、スレッドごとの地球環境
あなたが述べたように、let
は言ったバインディングの新しいスコープを作成するには名前に値をバインドします。
結合対の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
2番目の例を動作させるには、^:dynamicがxを0(動的に)に定義する必要があります。 – John
このプラスhttp://en.wikipedia.org/wiki/Scope_(programming)#Static_versus_dynamic_scopingは本当に私の理解を進歩させました。ありがとうございます! – Carl
xはエラーをスローしないためには^:動的ヒントでバインドする必要があります。 – WeGi