如何在clojure宏中从递归中断条件?
如果任何操作返回false,我希望中断宏计算的执行 预期产出:如何在clojure宏中从递归中断条件?,clojure,Clojure,如果任何操作返回false,我希望中断宏计算的执行 预期产出: (defmacro block [ctx & expr] `(let [~@(mapcat (fn [[k v]] [k `~v]) ctx)] ~@expr )) (defn action1 [] (print "action1") (rand-nth [true false])) (defn action2 [] (print "action2") (rand-nth [true f
(defmacro block [ctx & expr]
`(let [~@(mapcat (fn [[k v]] [k `~v]) ctx)]
~@expr
))
(defn action1 [] (print "action1") (rand-nth [true false]))
(defn action2 [] (print "action2") (rand-nth [true false]))
( block { __blockaddrabsolute "1_1" __blockaddr "1_1"}
( block {typeofparent "ummutate" __nodeid "c21f80" __blockaddr "1_1_1"} ( action1 ))
( block {__blockaddrabsolute "1_1_2" __nodeid "c60590" __blockaddr "1_1_2"} ( action2 ))
( block {__blockaddrabsolute "1_1_3" __nodeid "c60595" __blockaddr "1_1_3"} ( action1 ))
( block {__blockaddrabsolute "1_1_4" __nodeid "c60596" __blockaddr "1_1_4"} ( action2 ))
"end" )
您想要的短路行为可以通过
if
/when
表单获得,因此我们可以使用宏将主体中的一系列表单转换为嵌套的when
表单:
action1 true
action2 true
action1 false
然后,如果我们macroexpand
您的示例block
表单,我们会得到这个(为了可读性而重新格式化):
因为您的action1
/action2
函数返回随机布尔值,您将得到不同的结果,但您确实得到了所需的短路行为。如果任何嵌套表单在测试时未通过,最终结果将为零
我将考虑重构,通过引入一个更为集中、通常有用的<代码> Do/<代码>类宏,当它的任何内部形式都不真实时,它就短路了,根本不关心绑定。然后对内部绑定使用
let
:
(let* [__blockaddrabsolute "1_1" __blockaddr "1_1"]
(when (block {typeofparent "ummutate", __nodeid "c21f80", __blockaddr "1_1_1"} (action1))
(when (block {__blockaddrabsolute "1_1_2", __nodeid "c60590", __blockaddr "1_1_2"} (action2))
(when (block {__blockaddrabsolute "1_1_3", __nodeid "c60595", __blockaddr "1_1_3"} (action1))
(when (block {__blockaddrabsolute "1_1_4", __nodeid "c60596", __blockaddr "1_1_4"} (action2))
"end")))))
如果action1和action2是宏而不是函数(defmacro action1[]`(让[~'标志(rand nth[true false]))(do(println(str“action1”~'标志))~'标志))
@Jai,假设您的内部宏扩展为有效代码,那应该没问题。我想提出的另一个建议是,尝试从数据转换的角度来考虑这个问题,而不是从命令式语句的角度来考虑。这似乎可以表示为一棵树,并用简单的函数进行计算。
(let* [__blockaddrabsolute "1_1" __blockaddr "1_1"]
(when (block {typeofparent "ummutate", __nodeid "c21f80", __blockaddr "1_1_1"} (action1))
(when (block {__blockaddrabsolute "1_1_2", __nodeid "c60590", __blockaddr "1_1_2"} (action2))
(when (block {__blockaddrabsolute "1_1_3", __nodeid "c60595", __blockaddr "1_1_3"} (action1))
(when (block {__blockaddrabsolute "1_1_4", __nodeid "c60596", __blockaddr "1_1_4"} (action2))
"end")))))
(defmacro do-when [x & xs]
(if xs
`(when ~x (do-when ~@xs))
`~x))
(do-when
(let [x 1 y 2] (println "step 1") (= x (dec y)))
(rand-nth [true false])
"randomly successful result")