开发者

Function arguments multiple types

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 开发者_如何学Pythonwas wondering is there a better way to achive this kind of behavior?


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.


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 :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜