2012-10-02 20 views
9

Estoy leyendo in the API docs que la variable *file* debe tener un valor de "la ruta del archivo que se está evaluando, como una cadena". Sin embargo, esta característica parece estar rota en ciertos casos.* archivo * variable no funciona

Cuando ejecuto un archivo usando lein exec, las cosas funcionan como se esperaba:

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

Sin embargo, cuando corro una prueba que contiene una llamada a (println *file*), NO_SOURCE_PATH se imprime en lugar del archivo que contiene esa línea.

¿Por qué veo este comportamiento y cómo puedo acceder de forma confiable a la ruta y al nombre del archivo que se está evaluando?

Respuesta

13

*file* se establece en la ruta del archivo que se compilan , así que después de todo se compila el programa ya no es útil mirar el valor de *file* (suponiendo que no hay uso de eval).

En su ejemplo test.clj, se ejecuta println mientras el archivo todavía se está compilando. Si la referencia a *file* se mueve a una prueba o función, solo se eliminará la referencia en el tiempo de ejecución después de que el valor de *file* ya no sea útil.

Una opción es escribir una macro que almacena el valor de *file* cuando se expande, por lo que el resultado se puede utilizar más adelante. Por ejemplo, un archivo example.clj podría tener:

(defmacro source-file [] 
    *file*) 

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

Luego, desde el REPL o en cualquier lugar, (foo 42) imprimiría:

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

Tenga en cuenta que no importa qué archivo se define en source-file, sólo cuando fue expandido, ese es el archivo donde se define foo. Esto funciona porque es cuando se compila foo que se ejecuta source-file, y el valor de retorno de source-file que es solo una cadena se incluye en la versión compilada de foo. Por supuesto, la cadena está disponible cada vez que se ejecuta foo.

Si este comportamiento es sorprendente, puede ser útil considerar lo que debería suceder para que *file* tenga un valor útil dentro de cada función en tiempo de ejecución. Su valor tendría que cambiar para cada llamada y retorno de función, una sobrecarga de tiempo de ejecución sustancial para una característica rara vez utilizada.

+0

Gran explicación; ¡muchas gracias! –