Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在clojure宏中从递归中断条件?_Clojure - Fatal编程技术网

如何在clojure宏中从递归中断条件?

如何在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

如果任何操作返回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 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")