gpt4 book ai didi

macros - 使用线程宏时命名函数和匿名函数之间的奇怪区别

转载 作者:行者123 更新时间:2023-12-04 11:51:32 26 4
gpt4 key购买 nike

关于 Clojure 中的线程宏,我必须遗漏一些东西。

我有一张 map ,其值也是 map ,我想在另一个查找的结果中查找。让 map 做一个简单的{:a {:b 2}} -- 首先我要查 key :a ,这将产生 {:b 2} ,然后查找 b ,结果是 2 .第二次查找的键必须是函数的结果。

((fn [x] (get x :b)) ({:a {:b 2} } :a ))
=> 2

好的,让我们使用线程宏使其更具可读性。
(-> {:a {:b 2} } :a (fn [x] (get x :b)))

IE。申请 :a作为 map 上的一个函数,然后应用另一个函数。好吧,这不起作用: CompilerException java.lang.IllegalArgumentException: Parameter declaration :a should be a vector
奇怪的是,如果匿名函数被提取到一个命名函数,那么它工作正常:
(defn f [x] (get x :b))
(-> {:a {:b 2} } :a f)
=> 2

甚至:
(def f (fn [x] (get x :b)) ) 
(-> {:a {:b 2} } :a f)
=> 2

为什么命名函数和匿名函数的工作方式不同?

最佳答案

线程宏通过递归插入先前形式作为每个子形式的第一个参数,在评估该形式之前查看并更改系列中的每个子形式。

你开始:

(-> {:a {:b 2} } :a (fn [x] (get x :b)))

这变成:
(-> (:a {:a {:b 2}}) (fn [x] (get x :b)))

这变成:
(fn (:a {:b {:b 2}}) [x] (get x :b)))

这显然不是你想要的。

但是让我们看看如果在匿名函数周围添加额外的括号会发生什么:
(-> {:a {:b 2}} :a ((fn [x] (get x :b))))

(-> (:a {:a {:b 2}}) ((fn [x] (get x :b))))

(-> ((fn [x] (get x :b)) (:a {:a {:b 2}})))

((fn [x] (get x :b)) (:a {:a {:b 2}}))

-> 的最后一次递归宏展开中表单我们现在留下了可以执行您想要的操作的有效代码。

关于macros - 使用线程宏时命名函数和匿名函数之间的奇怪区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26205371/

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