clojure:with-redefs不能使用clojure.core函数吗?

时间:2014-04-19 06:25:54

标签: clojure

我对with-redefs提出了疑问。以下示例无法按预期工作。 在findmax中,始终调用clojure.core/max而不是匿名函数 with-redefs声明。

(defn findmax [x y]
  (max x y))

(with-redefs (clojure.core/max (fn [x y] (- x y)))
  (findmax 2 5))

当我进行以下更改时,一切都按预期工作:

(defn mymax [x y]
  (max x y))

(defn findmax [x y]
  (mymax x y))

(with-redefs (my/max (fn [x y] (- x y)))
  (findmax 2 5))

我在这里做错了什么?

1 个答案:

答案 0 :(得分:8)

对于大于1的arity,Clojure编译器会内联

max,因此在编译的代码中没有对Var #'clojure.core/max的引用,也无法更改使用{的代码片段的行为{1}}通过更改其根绑定。对于arity 1,这不会发生:

#'max

这由(defn my-max [& args] :foo) (with-redefs [clojure.core/max my-max] (max 0)) ;= :foo (with-redefs [clojure.core/max my-max] (max 0 1)) ;= 1 (with-redefs [clojure.core/max my-max] (max 0 1 2)) ;= 2 ;; and so on 来源中的密钥:inline:inline-arities的条目控制;见max

(source max)中有很多自动内联函数 - 主要是简单的算术运算。客户端代码可以自由定义新的(通过附加显式clojure.core和可能的:inline元数据或使用:inline-arities)。预期效果类似于定义宏,但内联函数仍可用于高阶用法。重要的是要注意当前的实现有其惊喜(例如,参见Clojure JIRA中的CLJ-1227,以及与之相关的最新问题),因此在一天结束时,对于客户端代码,仔细使用常规宏和伴随函数可能暂时是优选的。将来,内联函数很可能会被与编译器宏配对的常规函数​​所取代 - 这就是ClojureScript模型。