5

假设您具有以下三个函数,即 arity 1、2 和 3:

(defn I [x] x)
(defn K [x y] x)
(defn S [x y z] (x z (y z)))

clojure 是否有评估函数或习语来评估:

(I K S I I) as (I (K (S (I (I)))))

返回 arity 2 的偏函数?

我正在考虑创建一个宏,它可以采用上面的简单函数定义并将它们扩展为可以返回部分结果的多参数函数。如果已经有内置或惯用的方法来完成此操作,我不想创建宏。

以下是扩展宏对上述功能的要求:

(defn I
  ([x] I x)
  ([x & more] (apply (I x) more)))

(defn K
  ([x] (partial K x))
  ([x y] x)
  ([x y & more] (apply (K x y) more)))

(defn S
  ([x] (partial S x))
  ([x y] (partial S x y))
  ([x y z] (x z (y z)))
  ([x y z & more] (apply (S x y z) more)))
4

1 回答 1

5

我不确定我是否完全理解您要做什么,但是该comp功能对于执行您似乎在谈论的这种“功能链接”很有用。例如:

user> ((comp vec rest list) 1 2 3 4 5)
=> [2 3 4 5]

这相当于:

user> (vec (rest (list 1 2 3 4 5)))
=> [2 3 4 5]

在您的情况下,如果您有 list (I K S I I),并且您想将其评估为(I (K (S (I (I))))),我会使用(reduce comp ...),但您也可以使用(apply comp ...).

user> ((reduce comp [vec rest list]) 1 2 3 4 5)
=> [2 3 4 5]
user> ((apply comp [vec rest list]) 1 2 3 4 5)
=> [2 3 4 5]

您可能还对->or->>宏感兴趣。这些宏将它们的参数顺序嵌套到下一个参数中。宏将->嵌套到下一个表达式的第一个位置,而->>宏将嵌套到下一个表达式的最后一个位置。如果“下一件事”是一个函数,则两者的行为相同,并形成 的表达式(function nested-things-so-far),然后继续。

真的,例子是最好的:

(-> 1 (+ 10) (- 100) inc)
;//Expands to...
(inc (- (+ 1 10) 100))
;//Evaluating in the REPL...
user> (-> 1 (+ 10) (- 100) inc)
=> -88

(->> 1 (+ 10) (- 100) inc)
;//Expands to...
(inc (- 100 (+ 10 1)))
;//Evaluating in the REPL...
user> (-> 1 (+ 10) (- 100) inc)
=> 90

但是,您似乎更像是想做一些涉及自动柯里化的事情(尽管我认为我并不完全理解),为此我不知道任何预先存在的内置方式。

于 2012-08-12T00:55:33.173 回答