Clojure 在映射内部使用的函数上使用redefs
我想知道下面的片段中发生了什么。为什么在不强制对序列求值的情况下不能正确地重新定义函数Clojure 在映射内部使用的函数上使用redefs,clojure,Clojure,我想知道下面的片段中发生了什么。为什么在不强制对序列求值的情况下不能正确地重新定义函数 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
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>
谢谢 不同之处在于,当调用
foo
时,vector
作为map
的一个参数,将被计算一次(在本例中,这意味着将其解析为函数对象),而无需再次解析。即使您的代码使用redefs退出,也会使用相同的函数对象
然而,在bar
中,vector
不是map
的参数,而是一个匿名函数,它按名称引用vector
。结果是,虽然匿名函数只计算一次,vector
将在每次调用匿名函数时解析。因为map
是惰性的,所以这是在代码已经使用redefs退出之后发生的(除了您的力评估时)
关键的一点是,在函数调用中,如(映射向量(范围3))
,每个参数都会被计算,调用函数会得到这些计算的结果。这意味着map
调用foo
将获得重新定义的向量
,而map
调用bar
将获得一个函数,调用该函数时仍需按名称查找vector
org提供了一些关于如何将符号解析为对象的详细信息。这也是一个例子