函数参数有多种类型

时间:2011-09-07 15:10:29

标签: clojure

我试图推迟各种计算。我有以下形式的功能,

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

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

这允许我传递a-fn,值或返回值的函数

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

我所做的是构建一个函数列表(如上所述)来操作某些数据,fns可能会使用其他fns来检索它们的参数,或者在某些情况下事情不会改变,并且它们被赋值为参数。我想知道是否有更好的方法来实现这种行为?

2 个答案:

答案 0 :(得分:6)

您可以使用delayforce

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

如果您尝试使用类似(delay (prn :hello) 1)的内容来测试计算何时完成,请注意打印Delay对象会强制它;所以(def x (delay ...))是安全的,但在REPL提示符中键入普通(delay ...)则不然。

答案 1 :(得分:2)

可能有更优雅的方式来做你想要的,但这里至少是一个更通用的版本:

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

(def a-fn (partial delayed +))

所以delayed采用任意函数和函数/值列表。如果扩展所有args然后将函数应用于它们。然后,我们使用partial使用a-fn定义您的+

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

或者,delayed返回函数而不是使用partial可能是有意义的。请注意哪个更好。

欢迎比“延迟”更好的名字:)