2016-08-30 6 views
22

F#が何をしたいほとんど常にある=オペレータのための構造的な平等を使用しています。 F#の参照平等をチェックするにはどうすればよいですか?

let a = [1; 2; 3] 
let b = [1; 2; 3] 
printfn "%A" (a = b) // Prints "true" 

しかし、いくつかのアルゴリズムでは、「頼むことができるように重要になることが

は、これら二つのものです 同じオブジェクト ? "これは、例えば、グラフのサイクルを検出するのに役立ちます。だから私はF#の参照平等を求めるのですか?つまり、下記の isSameObject関数はどのように記述しますか?

let isSameObject x y = ??? 
let a = [1; 2; 3] 
let b = [1; 2; 3] 
let a' = a 
printfn "%A" (isSameObject a b) // Prints "false" 
printfn "%A" (isSameObject a a') // Prints "true" 

答えて

34

答えは、結局のところ、LanguagePrimitives.PhysicalEqualityを使用することです:

let isSameObject = LanguagePrimitives.PhysicalEquality 
let a = [1; 2; 3] 
let b = [1; 2; 3] 
let a' = a 
printfn "%A" (isSameObject a b) // Prints "false" 
printfn "%A" (isSameObject a a') // Prints "true" 

私はこのことについて尋ねたスタックオーバーフロー上で見つけることができ、正確に一つの質問がありました: short-cutting equality checking in F#?そして、その質問の対象からはほとんどそれを過ぎて私に一目惚れさせました、私は質問をもう一度尋ねる(そして答える)と思った。うまくいけば、この質問の件名は、「F#での参照平等」のような用語のためにグーグルで見つけやすくなります。

obj.ReferenceEqualsについて

コメントで、Fyodor Soikinは何が間違っているのかをobj.ReferenceEqualsに尋ねます。答えは、「あまりない」が、LanguagePrimitives.PhysicalEqualityは、ほとんどのF#コードについてobj.ReferenceEqualsよりも優れている2つの方法があります。

1)は、あなたがそれを二つの異なるタイプを渡すときobj.ReferenceEqualsはちょうど2つのobjをとりながらPhysicalEqualityは、コンパイラエラーがスローされますしたがって、Sと喜んchar listint listを比較しようとします:

let a = [1;2;3] 
let b = ['a';'b';'c'] 

obj.ReferenceEquals(a,b) // Returns false 
LanguagePrimitives.PhysicalEquality a b // Compiler error 

2)PhysicalEqualityは、あなたが値型を比較す​​るだけで参照タイプをさせません。 obj.ReferenceEqualsは、2つの値の型を比較させ、最初に暗黙的にボックスに入れます。

let n = 3 
let n' = n 
obj.ReferenceEquals(n,n') // Returns false! 
LanguagePrimitives.PhysicalEquality n n' // Compiler error 

そして、もちろん、個人的に沸く一つの他の違いが、あります:それは常にあなたがそれを「同じ」値オブジェクトを与えた場合でも、falseを返しれることを意味しかし、ボックス別途各1、使いやすさと使いやすさを提供します。 PhysicalEqualityはカレースタイルのパラメータを取ります。これは型推論と部分的なアプリケーションでうまくいきます。 obj.ReferenceEqualsは、タプルスタイルのパラメータを取ります。これは、使用するにはやや醜いことを意味します。

これらの理由から、obj.ReferenceEqualsよりものほうが、がよく、それぞれになります。

+3

良い古い 'obj.ReferenceEquals'には何も間違っていますか? –

+0

@FyodorSoikin - 私はあなたの質問に答えて2つのコメントを書いた後、答えの中でコード例を使ってよりうまくいくことに気付きました。そこで、あなたは行く: 'obj.ReferenceEquals'は**悪い**ではありませんが、2つの異なる型を比較しようとすると型のエラーが出るので、' PhysicalEquality'が優れています。 (これはほぼ確実にあなたのコードのバグであり、あなたが*それをキャッチするためにコンパイラを望んでいる)。 – rmunn

関連する問題