简体   繁体   中英

clojure: with-redefs doesn't work with clojure.core functions?

I've a question about with-redefs . The following example doesn't work as expected. In findmax , clojure.core/max is always called instead of the anonymous function in the with-redefs statement.

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

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

When I make the following changes everything works as expected:

(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))

What am I doing wrong here?

max is inlined by the Clojure compiler for arities greater than 1, so there is no reference to the Var #'clojure.core/max in the compiled code and no way to change the behaviour of code fragments that use #'max by changing its root binding. For arity 1, this does not happen:

(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

This is controlled by the entries at keys :inline and :inline-arities in the source of max ; see (source max) .

There are quite a few automatically inlined functions in clojure.core -- mostly the simple arithmetic operations. Client code is free to define new ones (by attaching explicit :inline and possibly :inline-arities metadata or by using definline ). The expected effect is similar to defining a macro, except an inlined function is still available for higher-order usage. It's important to note that the current implementation has its surprises (see CLJ-1227 in the Clojure JIRA, for example, and the more recent issues linked therefrom), so at the end of the day, for client code, careful use of regular macros and companion functions is likely to be preferable for the time being. In the future, inlined functions may well be replaced by regular functions paired with compiler macros -- this is the ClojureScript model.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM