1

私は1つのnsで以下を定義しました -

サービスアトムと、そのアトムに追加する別の関数があります -

(ns ex.first)

(def services (atom []))

(defn add-service
  [fns]
  (swap! services conj fns))

別のnsの私のコードでは、これを行います-

(ns ex.second ..)

(add-service [fn1 fn2 fn3])

1) コードをコンパイルする repl を実行すると、ベクトルがアトムに追加されると想定しています。ただし、評価する@servicesと が返されます[]

2)(add-service [fn1 fn2 fn3])replで評価すると、上記は機能します。

add-service3) fn をマクロに変換する方法も試しました。@servicesしかし、それでも空であることがわかります。

誰かがこれらについて助けてくれれば幸いです-

1) add-service 呼び出しが、コードのコンパイル時にベクトルをアトムに追加しないのはなぜですか?

  • add-serviceとして定義されますfn
  • add-serviceとして定義されますmacro

2)どうすれば機能しますか:)

4

1 に答える 1

4

project.clj で設定:aotしたかどうかによって異なります。:all

の場合、関数呼び出し:aotはrepl が開始されるとすぐに実行されます。それ以外の場合は、名前空間:allをロードする必要があります (例: using )。ロードすると、ns がコンパイルされ、対応するクラスが jvm にロードされ、関数呼び出しが実行されます。ex.seconduse

また、関数呼び出しはコンパイル時に発生しません。コンパイルされたクラス (名前空間を表す) が jvm によってロードされるときに発生します。

更新(コメントに基づく):

マクロにする場合は、aot のことも考慮する必要があります。

aot が名前空間をコンパイルするように設定されている場合、lein は jvm を作成し、そこにコードをロードし、コードを読み取り、マクロを実行してコードをコンパイルする clojure コンパイラを呼び出します。この時点で、この jvm (コンパイルに使用されます)あなたのコード)にはservices、マクロ実行のcozで満たされたアトムがありますが、このjvmはコンパイル専用でした。次に、lein は run コマンド用に別の jvm を作成し、その jvm にコンパイルされたクラスをロードしますが、この jvm にはservices、クラスに入力するコードがないため、入力されたクラスがありません。

aot が設定されていない場合、読み取り、マクロ展開、コンパイルのプロセスが lein run jvm で発生するため、マクロは機能しますが、ns のロードが発生した場合のみです。

「nsをロードせずに」懸念される限り、あなたができることはex.secondproject.clj:aot

于 2013-04-04T08:57:05.440 に答える