我试图推迟各种计算。我有以下形式的功能,
(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来检索它们的参数,或者在某些情况下事情不会改变,并且它们被赋值为参数。我想知道是否有更好的方法来实现这种行为?
答案 0 :(得分:6)
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可能是有意义的。请注意哪个更好。
欢迎比“延迟”更好的名字:)