72

*compile-path*1つは設定に機能し、もう1つは機能しないため、それらが異なることを理解しています。ただし、なぜそれらが異なるのかについての助けが必要です。

let指定されたバインディングで新しいスコープを作成しますが、binding...?

4

3 に答える 3

111

letある値に対して字句スコープの不変エイリアスを作成します。 binding一部の に対して動的スコープのバインディングを作成しますVar

動的バインディングとは、bindingフォーム内のコードとそのコードが呼び出すすべてのコード (ローカルのレキシカル スコープ内になくても) が新しいバインディングを参照することを意味します。

与えられた:

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

binding実際には a の動的バインディングを作成しますが、var をローカル エイリアスでシャドウするだけですVarlet

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

binding修飾名を使用でき ( Vars で動作するため)、次の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

Varsletも参照してください。

于 2009-10-06T03:00:49.950 に答える
13

letとbindingの構文上の違いはもう1つあります。

バインドの場合、すべての初期値は、変数にバインドされる前に評価されます。これは、前の「エイリアス」の値を後続の定義で使用できる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
于 2010-11-11T01:44:39.390 に答える
9

bindingスレッドごとのグローバル環境で値を名前にバインドします

あなたが述べたように、let上記のバインディングの新しいスコープを作成します。

于 2009-10-06T02:16:03.347 に答える