Clojure: c-redefs not working with clojure.core functions?

I have a question about with-redefs . The following example does not work properly. In findmax , clojure.core/max always called instead of an anonymous function in with-redefs .

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

When I make the following changes, everything works as expected:

 (defn mymax [xy] (max xy)) (defn findmax [xy] (mymax xy)) (with-redefs (my/max (fn [xy] (- xy))) (findmax 2 5)) 

What am I doing wrong here?

+7
clojure
source share
1 answer

max is built in by the Clojure compiler for arities greater than 1, so there is no reference to Var #'clojure.core/max in the compiled code and there is no way to change the behavior of code fragments that use #'max by changing the 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 on the keys :inline and :inline-arities in the max source; see (source max) .

clojure.core has quite a few automatically built-in functions - basically simple arithmetic operations. Client code is free to define new ones (by adding explicit metadata :inline and possibly :inline-arities or using definline ). The expected effect is similar to the definition of a macro, except that the built-in function is still available to use a higher order. It is important to note that the current implementation has its surprises (see CLJ-1227 in Clojure JIRA, for example, and the latest problems associated with it), so at the end of the day for the client code, careful use of regular macros and functions of the concurrent user is likely to be preferable on this moment. In the future, built-in functions may be replaced by regular functions related to compiler macros - this is the ClojureScript model.

+7
source share

All Articles