如何在Clojure中测试函数是否有副作用?

时间:2011-01-02 16:17:28

标签: clojure

是否有功能或宏我可以执行以下操作:

(has-side-effects?  my-function  my-function-args)

:或类似的东西可以返回 true false ,或 {:副作用true / false,:result return_value)

我只需要一种简单的方法来测试哪些功能是无副作用的。

4 个答案:

答案 0 :(得分:7)

如果是您的某项功能,请添加一些元数据以标记是否有副作用。

然后您可以使用((meta f) :side-effects)

进行检查

如果是第三方功能,我无法知道(其他更改其代码以使用上述解决方案)。

实际上,即便如此,但它并不漂亮。您可以使用自己的函数包装该函数,该函数具有元数据。

另外,请记住,除了没有副作用外,纯函数还有一个附加属性。它的评估仅取决于其参数,而不取决于某些全局共享状态,如外部变量或系统时间。您也可以将其添加到元数据中。然后,您可以通过检查两个元数据条目来检查它是否真的是纯粹的。

但是,请注意:

对于将其他函数作为参数的函数,这根本不起作用。这是一个例子:调用map是否有副作用?

它不在这里:(map inc [1 2 3])

但它确实在这里:(map println [1 2 3])

因为传递的功能可能有也可能没有副作用。

答案 1 :(得分:7)

在一般情况下这是不可能的(除非你设法解决halting problem ...... :-))

但是,您可以考虑在特定情况下使用各种技术:

  • 创建一个您知道无副作用的功能“白名单” - 例如大多数核心Clojure API都是无副作用的
  • 根据Goran
  • 的建议,使用元数据标记您自己的功能
  • 对您控制的Java类/函数使用注释
  • 如果要检查特定Clojure参考文献的副作用,请在Clojure参考文献中使用watch(add-watch

答案 2 :(得分:5)

Clojure不是纯粹的功能性语言。它不像Haskell那样使用类型系统强制函数的纯度。所以,没有,没有(直截了当的)方法可以知道函数是否在Clojure中是无副作用的。

答案 3 :(得分:-1)

不,没有简单的方法可以肯定地得到“是”或“否”的答案。但是,您可以通过确定是否甚至可能在给定代码中产生副作用来回答“不”或“可能”。

如果您发现任何可能存在副作用的迹象,那么您可以返回“可能”。否则,您将返回“否”,因为没有副作用。

您可以通过查找表明可能发生副作用的表单来查看代码并进行猜测。任何'print','dosync',Java setter或newing-up Java对象都意味着副作用是可能的。

总之,我所知道的是不可能的答案。但是,没有/也许可能是。

相关问题