2012-10-02 12 views
9

Sto leggendo in the API docs che la variabile *file* dovrebbe avere un valore di "il percorso del file che viene valutato, come una stringa". Tuttavia, questa funzione sembra interrotta in alcuni casi.* file * variabile non funzionante

Quando eseguo un file usando lein exec, le cose funzionano come previsto:

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

Eppure, quando si esegue un test che contiene una chiamata a (println *file*), NO_SOURCE_PATH viene stampato al posto del file contenente quella linea.

Perché visualizzo questo comportamento e come posso accedere in modo affidabile al percorso e al nome file del file che viene valutato?

risposta

13

*file* è impostato il percorso del file essere compilato , così dopo tutto il vostro programma è compilato non è più utile considerare il valore di *file* (supponendo che non uso di eval).

Nell'esempio test.clj, lo println viene eseguito mentre il file è ancora in fase di compilazione. Se il riferimento a *file* viene spostato in un test o in una funzione, verrà cancellato in fase di runtime solo dopo che il valore di *file* non è più utile.

Un'opzione è scrivere una macro che memorizza il valore di *file* quando è espanso, in modo che il risultato possa essere utilizzato in un secondo momento. Ad esempio, un file example.clj potrebbe avere:

(defmacro source-file [] 
    *file*) 

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

Poi dal REPL o dovunque, (foo 42) sarebbe stampare:

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

Si noti che non importa quale file source-file è definito in, solo quando è stato ampliato, ovvero il file in cui è definito foo. Funziona perché è quando foo viene compilato che viene eseguito source-file e il valore restituito di source-file che è solo una stringa viene quindi incluso nella versione compilata di foo. La stringa è ovviamente disponibile ogni volta che viene eseguito foo.

Se questo comportamento è sorprendente, può essere utile prendere in considerazione ciò che dovrebbe accadere in modo che *file* abbia un valore utile all'interno di ogni funzione in fase di esecuzione. Il suo valore dovrebbe cambiare per ogni chiamata di funzione e restituire, un sovraccarico di runtime sostanziale per una caratteristica usata raramente.

+0

Grande spiegazione; grazie mille! –