简体   繁体   中英

with-redefs on functions used inside maps

I was wondering what is going on in the snippet below. Why isn't the function properly redefined without forcing the evaluation of the sequence?

user> (defn foo [] (map vector (range 3)))
#'user/foo
user> (defn bar [] (map #(vector %) (range 3)))
#'user/bar
user> (foo)
([0] [1] [2])
user> (bar)
([0] [1] [2])
user> (with-redefs [vector (fn [_] "what does the fox say?")] (foo))
("what does the fox say?" "what does the fox say?" "what does the fox say?")
user> (with-redefs [vector (fn [_] "what does the fox say?")] (bar))
([0] [1] [2])
user> (with-redefs [vector (fn [_] "what does the fox say?")] (vec (bar)))
["what does the fox say?" "what does the fox say?" "what does the fox say?"]
user> 

Thanks!

The difference is that when you call foo , vector , as an argument to map , is evaluated (which in this case means resolving it to a function object) once and doesn't need to be resolved again. That same function object is used even after your code has exited with-redefs .

In bar , however, it isn't vector that's an argument to map , but instead an anonymous function which references vector by name. The result is that while the anonymous function is only evaluated once, vector will be resolved every time the anonymous function is invoked. Because map is lazy, that's happening after the code has already exited with-redefs (except for when your force evaluation).

The key point is that in a function call - like (map vector (range 3)) - each of argument is evaluated and the calling function gets the result of those evaluations. That means the map call in foo gets the redefined vector , whereas the map call in bar gets a function which will still need to look up vector by name when it's invoked.

The Clojure.org page on evaluation provides some details on how symbols are resolved to objects. This is also an example of late binding .

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