gpt4 book ai didi

clojure - 映射内使用的函数的 with-redefs

转载 作者:行者123 更新时间:2023-12-02 12:56:26 26 4
gpt4 key购买 nike

我想知道下面的代码片段中发生了什么。为什么没有在不强制评估序列的情况下正确地重新定义函数?

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 的参数, 被评估一次(在本例中意味着将其解析为函数对象),不需要再次解析。即使您的代码退出后,也会使用相同的函数对象 with-redefs .

bar ,然而,它不是 vector这是 map 的一个论点,而是引用 vector 的匿名函数按名字。结果是,虽然匿名函数仅计算一次,vector每次调用匿名函数时都会得到解析。因为map是懒惰的,这是在代码已经退出之后发生的 with-redefs (你的力量评估时除外)。

关键点是在函数调用中 - 如 (map vector (range 3)) - 每个参数都会被评估,并且调用函数会获取这些评估的结果。这意味着map调用foo获取重新定义的vector ,而map调用bar获取一个仍需要查找的函数 vector调用时按名称。

Clojure.org page on evaluation提供有关如何将符号解析为对象的一些详细信息。这也是 late binding 的示例.

关于clojure - 映射内使用的函数的 with-redefs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19341516/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com