2011-11-10 18 views
7

Esta pregunta proviene puramente de "masterbation mental" y probablemente no tiene ningún valor práctico.Constantes en tiempo de compilación Clojure

Si defino un valor en Clojure usando def, ¿se puede inducir al compilador a evaluarlo en tiempo de compilación y no esperar hasta el tiempo de ejecución?

(def the-answer 42) 

(+ the-answer 1) 

supongo que podría definir una macro, pero la sintaxis de llamada se convierte en una especie de incómoda:

(defmacro the-answer [] 42) 

(+ (the-answer) 1) 

Esto también funciona, pero sigue siendo fea:

(+ `~the-answer 1) 

que también entienden (o cree) que Clojure evalúa expresiones constantes en tiempo de compilación:

(def milliseconds-per-day (* 24 60 60 1000)) 

Estoy aprendiendo Common Lisp, pero mi opinión es que Common Lisp soporta macros lector definidos por el usuario, por lo que podría definir una macro lector (algo así como #$) que evalúa el siguiente símbolo en tiempo de compilación:

(+ #$the-answer 1) 

Por cierto, esa sintaxis no es "más bonita" que la macro llamada.

¿Cómo hago que Clojure evalúe los valores constantes en el tiempo de compilación y reemplace la referencia con el valor real? ¿Ya lo hace?

Antes de que alguien comience a citar la Ley de Knuth ("la optimización prematura es la raíz de todos los males"), hago esta pregunta para comprender mejor los aspectos internos de la compilación de Clojure.

+0

Eso no es lo que es la pontificación. La Pontificación es hablar de manera pomposa o dogmática. –

+0

Sí, lo eliminé. – Ralph

Respuesta

11

Desde el Clojure 1.3 docs

==^2.14: defs const ==

^: const le permite nombrar los valores primitivos con referencia rápida.

(def constantes {: PI 3,14: e 2,71}) ​​

(def ^: pi const (: constantes pi)) (def ^: const E (: e constantes))

La sobrecarga de buscar: e y: pi en el mapa se produce en compilar tiempo, como (: constantes pi) y (: constantes e) se evalúan cuando se evalúan sus formularios de definición primaria .

5

Uno de los principales usos de las macroes es el cálculo en movimiento para compilar el tiempo, por lo que solo se realiza una vez. Con esto en mente, mi opinión es que las macros son la herramienta correcta para este y el conjunto adicional de () me parece que realmente ayuda a que las piezas especiales se vean especiales.

+0

Esa es una respuesta razonable, y yo estaba pensando lo mismo. La sintaxis es mejor que la alternativa '~ the-answer. – Ralph

2

`~foo es literalmente idéntico al foo en todos los casos - lo que usted piensa que está saliendo de la primera es una ilusión.

Creo que :const es probablemente la respuesta correcta, pero también puede usar symbol-macros de clojure.tools.macro - tiene symbol-macrolet y defsymbolmacro/with-symbol-macros para este propósito (y para otros usos).

+0

No me di cuenta de eso ~ ~ foo. Gracias. A medida que pienso más sobre el problema, el '^: const' parece ser el camino correcto, pero ** solo para primitivos ** (sin incluir las instancias de' String'). El problema con las cadenas es que el uso de una macro o const probablemente dará como resultado una comparación en tiempo de ejecución de los contenidos 'Cadena' y no las direcciones. Si la razón para hacer esto es por desempeño, es una pérdida. – Ralph

Cuestiones relacionadas