6

I am trying to delay various calculations. I have functions of the following form,

(defn a-fn [a b]
  (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 the value,

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

what I do is build a list of functions (like the one above) to operate on some data, fns may use other fns to retrieve their arguments or in some cases things don't change and they are assigned values as arguments. I was wondering is there a better way to achive this kind of behavior?

2 Answers 2

6

You can use delay and 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

If you try something like (delay (prn :hello) 1) to test when the computation is done, note that printing the Delay object forces it; so (def x (delay ...)) is safe, but typing a plain (delay ...) in the REPL prompt is not.

Sign up to request clarification or add additional context in comments.

1 Comment

Nice. Forgot about delay/force.
2

There might be a more elegant way to do what you want, but here's at least a more generic version of it:

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

(def a-fn (partial delayed +))

So delayed takes an arbitrary function and a list of function/values. If expands all the args and then applies the function to them. Then we use partial to define your a-fn using +:

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

Alternatively, it might make sense for delayed to return a function rather than using partial. Note sure which is better.

A better name than "delayed" is welcome :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.