当你不需要将某些东西定义为动态来重新定义它时,将某些东西定义为动态的重点是什么?

时间:2013-04-01 16:59:55

标签: clojure

在我看来,with-redefs可以执行动态符号binding可以执行的所有操作,只是它没有需要^:dynamic元数据的限制。那我什么时候应该使用另一个呢?

1 个答案:

答案 0 :(得分:17)

除了要求^:dynamic元数据之外,binding还创建仅在当前线程中可见的绑定,而with-redefs所做的绑定在所有线程中都可见。因此,with-redefs是一个非常生硬的工具,有可能影响在同一个VM中运行的其他代码。我从来没有见过with-redefs在测试代码之外使用,也不应该(至少在我看来)。

我会总结两者之间的差异:

  • 绑定 ^:dynamic 允许您以受控方式引入一些动态行为。这是一种在API中定义扩展点的好方法,它允许远离调用链的调用者改变代码的行为,而不必在调用堆栈中一直显式地传递参数(其中一些甚至可能不是他们的代码)。
  • with-redefs 是免费的。它在测试中很有用,例如当被测函数有很多依赖时,用于模拟整个子系统。

将var声明为^:dynamic,以及使用耳罩命名动态变量(例如*my-dynamic-var*)的惯例,还有一个额外的好处,即它是一种自我记录的向呼叫者做广告的方式您的部分代码可以动态修改。

总结:在编写API和生产代码时,首选 ^:动态绑定。在测试中使用 with-redefs ,并作为最后的手段,动态地改变未被声明为^:dynamic的控制之外的vars行为(然后谨慎使用)。