2012-02-22 6 views
13

私は、次のClojureの機能を持っていると仮定します。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) 

収益の一部と同等?

+1

不可能 - 機能の同等性は決めることができません。 –

+0

申し訳ありませんが、賞金のコメントフォーマットについてお詫び申し上げます。フォーマットが同じように機能しないことを認識していませんでした。 –

+1

こんにちはOmri。私の答えが以下のように分かれば、同じJVMのバイトコードを持つ2つの関数について説明しています。それは効果的な内的平等です。私はまた、内的平等が内向きの平等を意味するという点を立てています(しかしその逆は真ではありません)。バイトコードが異なる場合(あなたが与えたいくつかの例のように)、私たちは、私たちが知る限りundecideableである拡張の平等を達成しようとしています。希望が少し明確になりたい - 意図的な平等(いくつかの特別な場合を加えて)は、おそらく私たちが望むことができる最高のものです。 – kittylyst

答えて

3

Clojureは、2つの関数の同等性を判断する能力を持っていないこと、およびプログラムを機能的にテストすることができないことが証明されていることに同意する(ブラックボックステストとも呼ばれる) (入力セットが有限で定義されている場合を除いて)停止問題による等価性。

異なるフォーム(異なるバイトコード)を持っていても、代数的に2つの関数の等価性を判断できることを指摘したいと思います。

代数的に等価性を証明する方法は、1930年代にAlonzo Churchによって開発され、ラムダ微積分のベータ還元として知られています。このメソッドは、あなたの質問の単純なフォーム(同じバイトコードを生成する)と、異なるバイトコードを生成するより複雑なフォームにも当てはまります。

11

"関数式の等価性"が意味するものに正確に依存します。

これらの関数はバイトコードとして終わるので、たとえば、各関数に対応するバイトコードをバイト[]にダンプし、次に2つのバイトコード配列を比較することができます。

しかし、意味的に同等のメソッドを書くにはバイトコードに同じ表現を持たないさまざまな方法があります。

一般に、コードを実行せずにコードの内容を確認することは不可能です。可能なすべての入力に対して、2つのコードが同じであるかどうかを判断することは不可能です。

これは、少なくとも計算上は、停止問題と同じくらい悪く、おそらく悪化します。

停止問題はそのままでは決めることができないので、ここでの一般的な答えは絶対に(そしてClojureだけでなく、すべてのプログラミング言語について)です。

0

他の人の優秀な回答に追加することはできませんが、私を助けた別の視点を提供したいと思います。たとえば、正しい関数が自分自身の関数から返されているかどうかをテストします。関数オブジェクトを比較する代わりに、関数を返すだけで'symbolとなります。

私はこれがおそらく著者が求めているのではなく、単純な場合にはそうするかもしれないことを知っています。