代码之家  ›  专栏  ›  技术社区  ›  Reut Sharabani

`loop`和'with redefs`不能很好地配合使用

  •  2
  • Reut Sharabani  · 技术社区  · 6 年前

    loop . 经过一番调试我发现 with-redefs 一起玩得不好。我意识到使用

    我创建了一个MCVE来演示“问题”:

    (loop [test 3]
      (with-redefs []
        (if (zero? test)
          "done"
          (recur (dec test)))))
    

    这给了我:

    要重复的参数计数不匹配,应为:0个参数,得到:1

    带redefs 按预期工作:

    (loop [test 3]
      (if (zero? test)
        "done"
        (recur (dec test))))
    

    返回 "done"

    1 回复  |  直到 6 年前
        1
  •  8
  •   gfredericks    6 年前

    其原因在于经济的宏观扩张 with-redefs :

    (macroexpand-1
     '(with-redefs []
        (if (zero? test)
          "done"
          (recur (dec test)))))
    

    (with-redefs-fn {}
      (fn []
        (if (zero? test)
          "done"
          (recur (dec test)))))    
    

    因为一个新的 fn recur 是指那个 fn公司 而不是更远的地方 loop (这解释了arity异常)。

    还有许多其他宏与“不兼容” 这样,因为 重现 ,如果 重现 在宏调用内部发生时,宏可能正在操纵代码,以便 重现 不再处于尾部位置。

    对于 带redefs

    (loop [test 3]
      (let [[recur? val]
            (with-redefs []
              (if (zero? test)
                [false "done"]
                [true (dec test)]))]
        (if recur?
          (recur val)
          val)))