Arguments of functions of several types

I am trying to defer various calculations. I have functions of the following kind:

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

this allows me to pass a-fn, a value or a function that returns a value,

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

I create a list of functions (for example, above) to work with some data, fns can use other fns to extract their arguments, or in some cases things don’t change and they are assigned values ​​as arguments. I was wondering if there is a better way to achieve this behavior?

+6
source share
2 answers

You can use delay and force :

 user=> (defn a-fn [ab] (+ (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 xy) 3 user=> (a-fn x 2) 3 

If you try something like (delay (prn :hello) 1) to check when the calculation is done, note that printing the Delay object forces it; therefore (def x (delay ...)) is safe, but there is no simple (delay ...) input in the REPL request.

+6
source

There may be a more elegant way of doing what you want, but here is at least a more general version:

 (defn delayed [reducer & fs] (apply reducer (for [f fs] (if (fn? f) (f) f)))) (def a-fn (partial delayed +)) 

So, delayed accepts an arbitrary function and a list of function values ​​/. If extends all arguments and then applies a function to them. Then we use partial to determine your a-fn with + :

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

Alternatively, for delayed may need to return a function, rather than using a partial one. Notice which is better.

Better name than "delay" is welcome :)

+2
source

Source: https://habr.com/ru/post/896799/


All Articles