2012-10-02 8 views
9

in the API docsは、*file*の変数の値が "評価されるファイルのパスを文字列として"指定する必要があります。しかし、この機能は場合によっては壊れているようです。私はlein exec使用してファイルを実行すると* file *変数が動作しない

、物事が期待どおりに動作:私は(println *file*)への呼び出しが含まれているテストを実行したときに

$ cat test.clj 
(println *file*) 
$ lein exec test.clj 
/path/to/test.clj 

しかし、NO_SOURCE_PATHは、代わりにその行を含むファイルの印刷されます。

この現象が発生する理由と、評価するファイルのパスとファイル名に確実にアクセスする方法を教えてください。

答えて

13

*file*をコンパイルされたファイルのパスに設定されているので、あなたの全体のプログラムの後、*file*の値(evalの一切の使用を想定していない)を見て、もはや有益であるコンパイルされません。

test.cljの例では、ファイルがまだコンパイルされている間にprintlnが実行されます。 *file*への参照をテストまたは関数に移動すると、*file*の値が役に立たなくなった後で実行時に逆参照されます。

拡張されたときに値*file*を格納するマクロを記述すると、その結果を後で使用できるようになります。たとえば、ファイルexample.cljを持つことができ:次に

(defmacro source-file [] 
    *file*) 

(defn foo [x] 
    (println "Foo was defined in" (source-file) "and called with" x)) 

REPLからか、どこかに、​​は印刷になります。場合にのみ、で定義されているファイルsource-file関係ないことを

Foo was defined in /home/chouser/example.clj and called with 42 

注意を展開されたファイルは、fooが定義されているファイルです。これは、fooがコンパイルされ、source-fileが実行され、source-fileという戻り値が文字列であるため、fooのコンパイル済みバージョンに含まれているためです。文字列はもちろん、fooが実行されるたびに利用可能です。

この動作が驚くべき場合は、*file*が実行時にすべての関数の中で有効な値を持つために何が起こるのかを検討すると役立ちます。その値は、ほとんどの場合、ほとんど使用されない機能の実行時のオーバーヘッドになるよう、関数呼び出しおよび戻りごとに変更する必要があります。

+0

大きな説明;どうもありがとう! –

関連する問題