1

私のバックグラウンドには 10 年間の Common Lisp が含まれているため、今は名前空間にベクトル (つまり a、b、c) と Nvector バインディング (ab、ac、bc など) を含むシンボリック数学パッケージを作成し、print メソッドを定義して Clojure を学んでいます。これらのオブジェクトのために。

そのため、バインド関数と同じファイルの末尾に deftests を記述したとき、コンパイラの警告を回避するために記述 (ab ab を宣言) する必要がありました (これは完全に理にかなっています)。

    (def G3 (doall (ga-bindall "a b c")))
    galg.core=> G3
    (+a +b +c +a*b +a*c +b*c +a*b*c +a*b +a*c +b*c +a*b*c)
    galg.core=> [a +a -a ab +ab -ab a*b +a*b -a*b abc]
    [+a +a -a +a*b +a*b -a*b +a*b +a*b -a*b a*b*c]

    (deftest galg-vectors
      (declare a b ab)   ;<=== required when in same file as definitions
      (testing "GALG Vector, Nvector and Sum tests."
        (is (= (Vector 'a) a))
        (is (= (Vector 'a -1) -a))
        (is (= ab (Nvector 'a 'b)))
        (is (= (+ 1 a ab) (Sum 1 a ab)))
        ))

次に、テストをgalg.core-testファイルに移動してコードをクリーンアップすると、次のようになります。

    (ns galg.core-test (:use clojure.test galg.core))  ;;<== imports a, b, ab, etc
    (deftest galg-vectors
      ;(declare a b ab)   ;<=== must be removed when in separate file 
      (testing "GALG Vector, Nvector and Sum tests."
        (is (= (Vector 'a) a))
        (is (= (Vector 'a -1) -a))
        (is (= ab (Nvector 'a 'b)))
        (is (= (+ 1 a ab) (Sum 1 a ab)))
        ))

...次に、(declare ab ab) が存在する場合、「既に参照しています:」コンパイラ エラーが発生します。

CompilerException java.lang.IllegalStateException: a already refer to: #'galg.core/a in namespace: galg.core-test, compiling:(NO_SOURCE_PATH:2:3)

私の考えでは、「宣言」は実際にはコンパイラーの「バインディングの約束」であり、実際には定義していないため、このエラーは少し過剰に思えます。

何かご意見は?

4

2 に答える 2

1

declareそれほどスマートではありません。何かが後で作成されるという約束を実際に作成するのではなく、今作成し、常にローカルの名前空間で作成します。そうしないと、バインドされた値を必要とするものにバインドされていない値を使用しようとすると、例外がスローされます。def以前に定義された場合に、バインドされた値をバインドされていない値で上書きしないほどスマートです。

user> (macroexpand-1 '(declare a))
(do (def a)) 

ご覧のとおり、declare declare は、バインドされていない値を持つローカル変数を作成します。このローカル変数の作成が、表示されるエラーをトリガーしています。名前空間 (` ns ) 式により、その名前のエントリが既に名前空間に追加されているため、式が次の場合:

 (declare a b ab) 

実行すると、次のように展開されます。

 (do (def a) (def b) (def ab))

aその名前はすでに別の名前空間を参照しているため、エラーをトリガーするという名前のローカル名前空間に var を作成しようとします。

于 2013-10-22T23:04:53.373 に答える
0

同じ名前空間内で実行すると、どの順序でもエラーなしで定義および宣言できます。

user> (def a 0)
#'user/a
user> (declare a)
#'user/a

問題は、すべての clojure 変数が名前空間になっていることです。宣言は、変数が呼び出された名前空間に変数を作成します。use別の名前空間からシンボルを参照するために呼び出したので、それらを宣言すると新しい変数galg.core-test/aなどが作成され、使用していた変数などがシャドウされますgalg.core/a。エラー メッセージは、無関係な var がスコープ内の以前のものをシャドウしていることを示しています。のuse

于 2013-10-23T00:34:22.343 に答える