Clojure - 测试函数表达式的相等性?

haw*_*eye 14 expression equality function clojure

假设我有以下clojure函数:

(defn a [x] (* x x))

(def b (fn [x] (* x x)))

(def c (eval (read-string "(defn d [x] (* x x))")))
Run Code Online (Sandbox Code Playgroud)

有没有办法测试函数表达式的相等性 - 有些相当于

(eqls a b)
Run Code Online (Sandbox Code Playgroud)

返回true?

kit*_*yst 11

它完全取决于"函数表达式的相等性"的含义.

这些函数最终将作为字节码,因此我可以将每个函数对应的字节码转储到byte [],然后比较两个字节码数组.

但是,有许多不同的编写语义等效方法的方法,这些方法在字节码中的表示方式不同.

一般来说,如果不运行它就无法分辨出一段代码.因此,在所有可能的输入上,无法在不运行两个代码的情况下判断两位代码是否相等.

从计算上讲,这至少与暂停问题一样糟糕,甚至可能更糟.

暂停问题是不可判定的,因此这里的一般情况答案绝对没有(并且不仅仅适用于Clojure,而是适用于所有编程语言).


dan*_*lmo 3

我同意上述答案,因为 Clojure 没有内置的能力来确定两个函数的等价性,并且已经证明,您无法通过功能测试程序(也称为黑盒测试)来确定相等性,因为停止问题(除非输入集是有限的并且已定义)。

我想指出的是,可以通过代数确定两个函数的等价性,即使它们具有不同的形式(不同的字节码)。

用代数证明等价性的方法是由 Alonzo Church 在 1930 年代开发的,被称为 Lambda 微积分中的 beta 约简。此方法当然适用于您问题中的简单形式(这也会产生相同的字节代码),也适用于会产生不同字节代码的更复杂形式。