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

Zub*_*air 10 clojure

是否有函数或宏我可以执行以下操作:

(has-side-effects?  my-function  my-function-args)
Run Code Online (Sandbox Code Playgroud)

:或类似的东西可以返回truefalse,或者{:side-effects true/false,:result return_value)

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

Gor*_*vic 7

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

然后你可以检查它 ((meta f) :side-effects)

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

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

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

但是,请注意:

这简单地不适用于将其他函数作为参数的函数.这是一个例子:呼叫map有副作用吗?

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

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

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


mik*_*era 7

在一般情况下这是不可能的(除非你也设法解决暂停问题 ...... :-))

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

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


Abh*_*kar 5

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

  • 我觉得你的回答是误导性的.你的基础是Clojure不是纯粹的功能,也不会强迫功能上的纯度.然而,似乎你可以在Clojure中创建一个函数或宏,它可以回答"没有副作用可能发生"或"副作用可能".实际上可能有用的解决方案. (2认同)