5

Clojure ではアルファ変換が安全ではないことに驚きました。

Clojure> ((fn [o] (o 3 2)) +)
5

Clojure> ((fn [or] (or 3 2)) +)
3

Clojure> ((fn [def] (def 3 2)) +)
java.lang.RuntimeException: First argument to def must be a Symbol

(3 つのスニペットすべてが 5 に評価されると予想していました)。

シャドウイングとマクロ、および特殊なフォームが関係する場合のシンボル解決のルールは何ですか?

Try Clojureのバージョンを使用しています。

4

2 に答える 2

6

ドキュメントによると、特別なフォームをシャドウすることはできません。

シンボルが解決されます:

  • 名前空間で修飾されている場合、値は、シンボルによって名前が付けられたグローバル var のバインディングの値です。シンボルによって名前が付けられたグローバル var がない場合、または参照が別の名前空間の非パブリック var への参照である場合は、エラーになります。
  • パッケージ修飾されている場合、値はシンボルによって名前が付けられた Java クラスです。シンボル名の Class が無い場合はエラーとなります。
  • **それ以外の場合、認定されておらず、次の最初のものが適用されます。
    1. 特別なフォームに名前が付けられている場合、それは特別なフォームと見なされ、それに応じて使用する必要があります。**
    2. シンボルからクラスへのマッピングがあるかどうかを確認するために、現在の名前空間でルックアップが行われます。その場合、シンボルは Java クラス オブジェクトの名前であると見なされます。クラス名は通常、クラス オブジェクトを表しますが、'.' などの特定の特殊な形式では特別に扱われることに注意してください。そして新しい。
    3. ローカル スコープ (つまり、関数定義) 内にある場合は、ローカル バインディング (関数の引数や let バインド名など) に名前が付けられているかどうかを確認するためにルックアップが行われます。その場合、値はローカル バインディングの値です。
    4. シンボルから var へのマッピングがあるかどうかを確認するために、現在の名前空間でルックアップが行われます。その場合、値はシンボルによって参照される var のバインディングの値です。
    5. エラーです。

よくわかりませんが、この一節 (同じページから) は、マクロをシャドーできないことを意味すると解釈します。

マクロはフォームを操作する関数であり、構文の抽象化を可能にします。呼び出しの演算子が、マクロ関数であるグローバル var を指定するシンボルである場合、そのマクロ関数が呼び出され、未評価のオペランド形式が渡されます。次に、マクロの戻り値がその場所で評価されます。

演算子が特別なフォームまたはマクロでない場合、呼び出しは関数呼び出しと見なされます。

于 2012-08-16T13:29:44.440 に答える
3

最初の 2 つは両方とも私にとっては 5 と評価されます (Eclipse の Clojure 1.4 / 反時計回りの REPL)。3 を取得している場合は、Try Clojure にバグがあると思われます。

関数名とマクロ名の両方をローカルでシャドウできる必要があります (ただし、微妙で紛らわしいバグが発生する可能性があるため、多くの場合はお勧めできません!)。

def特殊なフォームであるため、3 番目は機能しません。特別なフォームは、Clojure リーダーやコンパイラから特別な扱いを受けるため、シャドウすることはできません。

于 2012-08-16T13:26:30.753 に答える