函数参数有多种类型

Ham*_*aya 6 clojure

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

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

        b (if (fn? b)
            b
            #(identity b))]
    (+ (a) (b))))
Run Code Online (Sandbox Code Playgroud)

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

(a-fn 1 2)    
(defn x [] 1)    
(defn y [] 2)    
(a-fn x y)
(a-fn x 2)
Run Code Online (Sandbox Code Playgroud)

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

Jou*_*nen 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
Run Code Online (Sandbox Code Playgroud)

如果您尝试(delay (prn :hello) 1)测试完成计算的时间,请注意打印Delay对象会强制它; 所以(def x (delay ...))是安全的,但(delay ...)在REPL提示符中输入plain 不是.


Dav*_*Ray 2

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

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

(def a-fn (partial delayed +))
Run Code Online (Sandbox Code Playgroud)

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

user=> (a-fn 1 2)
3
user=> (a-fn (constantly 1) 2)
3
user=> (a-fn (constantly 1) 2 4)
7
Run Code Online (Sandbox Code Playgroud)

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

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