2

REPL から次のコードを実行しようとすると (動的レコードで再生):

(defrecord (symbol "rec2") (vec (map symbol ["f1" "f2"])))

エラーが表示されるCompilerException java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol, compiling:(NO_SOURCE_PATH:23)

次のことを考慮して、この PersistentList を生成する場所を自問しています。

user=> (symbol "rec2")
rec2
user=> (vec (map symbol ["f1" "f2"]))
[f1 f2]

しかし、私の本当の質問は、次のコードが機能する理由です。

user=> (defrecord rec2 [f1 f2])
user.rec2

私も試しました:

user=> (clojure.core/defrecord (clojure.core/symbol "rec1") (vec (clojure.core/map clojure.core/symbol ["f1" "f2"])))
CompilerException java.lang.RuntimeException: Can't refer to qualified var that doesn't exist, compiling:(NO_SOURCE_PATH:40)

(修飾された var? 唯一の違いは、存在する関数名を完全に修飾していることです)明らかに、Clojure defrecord マクロの理解に何かが欠けていますが、マクロは単に AST 修飾子であると考えていたので、シンボルまたはシンボルに解決されるものは同じことなので、通常の形式が機能し、他の形式が機能しない理由を誰かに説明してもらいたいです!

ティア!

4

1 に答える 1

4

問題は次のとおりdefrecordです。マクロであり、すべての引数が評価されません。それらはマクロに渡されたので、期待どおり(symbol "rec2")ではなく、シンボルと文字列の2つの要素を含むリストが取得されます。rec2以下を試すことができます:

(eval `(defrecord ~(symbol "rec2") ~(vec (map symbol ["f1" "f2"])))) 

リスト(defrecord rec2 [f1 f2])を作成してから評価します。
しかし、一部のコードを動的に評価するのは良い考えではないと思います。他に何か方法があるのか​​もしれません。

于 2012-06-14T09:53:52.723 に答える