2011-09-07 33 views
6

Estoy intentando retrasar varios cálculos. Tengo funciones de la siguiente forma,Argumentos de función múltiples tipos

(defn a-fn [a b] 
    (let [a (if (fn? a) 
      a 
      #(identity a)) 

     b (if (fn? b) 
      b 
      #(identity b))] 
    (+ (a) (b)))) 

esto me permite pasar a-fn, un valor o una función que devuelve el valor,

(a-fn 1 2)  
(defn x [] 1)  
(defn y [] 2)  
(a-fn x y) 
(a-fn x 2) 

lo que hago es crear una lista de funciones (como el anterior) para operar con algunos datos, los fns pueden usar otros fns para recuperar sus argumentos o, en algunos casos, las cosas no cambian y se les asignan valores como argumentos. Me preguntaba si existe una mejor manera de lograr este tipo de comportamiento.

Respuesta

2

Puede haber una manera más elegante de hacer lo que quiere, pero aquí está, al menos, una versión más genérica de la misma:

(defn delayed [reducer & fs] 
    (apply reducer (for [f fs] (if (fn? f) (f) f)))) 

(def a-fn (partial delayed +)) 

Así delayed tiene una función arbitraria y una lista de funciones/valores. Si expande todos los argumentos y luego les aplica la función. Luego usamos partial para definir su a-fn usando +:

user=> (a-fn 1 2) 
3 
user=> (a-fn (constantly 1) 2) 
3 
user=> (a-fn (constantly 1) 2 4) 
7 

Alternativamente, podría tener sentido para delayed para devolver una función en lugar de utilizar parcial. Tenga en cuenta que es mejor.

un nombre mejor que el "retraso" es bienvenido :)

6

Usted puede utilizar delay y force:

user=> (defn a-fn [a b] (+ (force a) (force b))) 
#'user/a-fn 
user=> (a-fn 1 2) 
3 
user=> (def x (delay 1)) 
#'user/x 
user=> (def y (delay 2)) 
#'user/y 
user=> (a-fn x y) 
3 
user=> (a-fn x 2) 
3 

Si intenta algo así como (delay (prn :hello) 1) a prueba cuando se realiza el cálculo, tenga en cuenta que la impresión el objeto Delay lo fuerza; así que (def x (delay ...)) es seguro, pero escribir un simple (delay ...) en el prompt REPL no lo es.

+0

Agradable. Se olvidó de la demora/fuerza. –

Cuestiones relacionadas