2010-12-18 8 views
11

Más por curiosidad que cualquier otra cosa (pero con la expectativa de que ocasionalmente podría ser un truco útil para ajustar el rendimiento), ¿es posible usar macros Clojure para "alinear" una función existente?Alinear una función con macros Clojure

es decir, me gustaría ser capaz de hacer algo como:

(defn my-function [a b] (+ a b)) 

(defn add-3-numbers [a b c] 
    (inline (my-function 
    a 
    (inline (my-function 
     b 
     c))))) 

Y tienen que producir (en tiempo de compilación) exactamente la misma función que si hubiera inline las adiciones a mí mismo, tales como:

(defn add-3-numbers [a b c] 
    (+ a (+ b c))) 
+0

¿Observó la función 'apply'? http://clojuredocs.org/clojure_core/clojure.core/apply – edbond

+1

aplicar trabajos dinámicamente en el tiempo de ejecución, estoy buscando algo que realice la creación en tiempo de compilación .... – mikera

+0

'(cadena de lectura (clojure.repl) fuente-fn \ 'mi-función))' parece un buen punto de partida! – vemv

Respuesta

14

En caso de que no lo sabía, se pueden definir las funciones inline utilizando definline

(doc definline) 
------------------------- 
clojure.core/definline 
([name & decl]) 
Macro 
    Experimental - like defmacro, except defines a named function whose 
    body is the expansion, calls to which may be expanded inline as if 
    it were a macro. Cannot be used with variadic (&) args. 
nil 

también la comprobación de la fuente,

(source definline) 
------------------------- 
(defmacro definline 
    [name & decl] 
    (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] 
    `(do 
     (defn ~name [email protected] ~args ~(apply (eval (list `fn args expr)) args)) 
     (alter-meta! (var ~name) assoc :inline (fn ~name ~args ~expr)) 
     (var ~name)))) 

definline define simplemente una var con meta-datos {:inline (fn definition)}. Entonces, aunque no es exactamente lo que estaba preguntando, puede volver a enlazar la var con nuevos metadatos para obtener un comportamiento inline.

+0

enlace útil: esto definitivamente parece una herramienta útil en muchas situaciones. la diferencia clave con lo que estoy buscando es que parece requerir que la función se defina explícitamente como en línea, mientras que yo quiero ser capaz de alinear una función arbitraria – mikera

+0

No he buscado su implementación, pero insinué una solucion potencial. Puede intentar escribir una macro que vuelva a enlazar las funciones var a uno con metadatos que contengan la etiqueta: inline. El problema clave que tendría que resolverse es garantizar que la reenlace se realice en tiempo de compilación en lugar de en tiempo de ejecución. – bmillare

Cuestiones relacionadas