【问题标题】:Clojure - test for equality of function expression?Clojure - 测试函数表达式的相等性?
【发布时间】:2012-02-22 11:15:22
【问题描述】:

假设我有以下 clojure 函数:

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

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

(def c (eval (read-string "(defn d [x] (* x x))")))

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

(eqls a b)

返回真?

【问题讨论】:

  • 不可能——函数的等价性是不确定的。
  • 糟糕,对于赏金评论格式感到抱歉——没有意识到格式不会以同样的方式工作。
  • 你好奥姆里。如果您在下面看到我的回答,您会看到我讨论了两个函数,它们具有与它们的主体相同的 JVM 字节码。这实际上是内涵平等。我还指出,内涵平等意味着外延平等(但反过来不正确)。如果字节码最终不同(就像您给出的某些示例可能那样),那么我们将重新尝试实现扩展相等 - 正如我们所知,这是无法确定的。希望这能让事情更清楚一点——内涵平等(加上一些特殊情况)可能是我们所能希望的最好的。
  • @kittylyst 感谢您的回复,我觉得您的回答很周到。我越来越相信特殊情况的数量(如您所说)实际上非常大,以至于我们可以有意义地测试功能等效性。例如,我认为(* x x) 等于(* x x 1) 的情况可以通过注意* 函数的标识值是1 来解决。更一般地,我们可以通过获取(f) 的结果来测试身份值。如果给定的f 确实有一个标识值,我们可以在等价测试时忽略某些(f ...) 中的所有这些值。
  • @kittylyst 另外:如果你知道获取函数体的 JVM 字节码的方法,我很想学习如何——这听起来很酷。

标签: function clojure expression equality


【解决方案1】:

这完全取决于您所说的“函数表达式的相等性”。

这些函数最终会变成字节码,因此我可以将每个函数对应的字节码转储到一个字节[],然后比较两个字节码数组。

但是,有许多不同的方法可以编写语义等效的方法,它们在字节码中的表示形式不同。

一般来说,如果不运行一段代码,就不可能知道它做了什么。因此,如果不在所有可能的输入上运行它们,就不可能判断两个代码是否等效。

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

停机问题是无法确定的,因此这里的一般情况答案肯定是否定的(不仅适用于 Clojure,而且适用于所有编程语言)。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      我无法补充其他人的出色答案,但想提供另一个对我有帮助的观点。如果你是例如测试您自己的函数是否返回了正确的函数,而不是比较函数对象,而只是将函数返回为'symbol

      我知道这可能不是作者要求的,但对于简单的情况它可能会这样做。

      【讨论】:

        猜你喜欢
        • 2012-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-03
        • 2018-01-20
        • 2021-09-24
        相关资源
        最近更新 更多