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"
答案 0 :(得分:40)
事实证明,答案是使用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"
我可以在Stack Overflow上找到一个问题: short-cutting equality checking in F#?由于那个问题的主题几乎让我一目了然,我想我会再问(并回答)这个问题。希望这个问题的主题行能够更容易地找到谷歌搜索术语,例如" F#"中的参考平等。
obj.ReferenceEquals
怎么样?
在评论中,Fyodor Soikin询问obj.ReferenceEquals
的错误。答案是"并不多",但对于大多数F#代码,LanguagePrimitives.PhysicalEquality
有两种方式优于obj.ReferenceEquals
:
1)PhysicalEquality
在传递两种不同类型时会抛出编译错误,而obj.ReferenceEquals
只需要两个obj
,因此很乐意尝试将int list
与char list
进行比较let a = [1;2;3]
let b = ['a';'b';'c']
obj.ReferenceEquals(a,b) // Returns false
LanguagePrimitives.PhysicalEquality a b // Compiler error
:
PhysicalEquality
2)obj.ReferenceEquals
不允许您比较值类型,只比较引用类型。 let n = 3
let n' = n
obj.ReferenceEquals(n,n') // Returns false!
LanguagePrimitives.PhysicalEquality n n' // Compiler error
将允许您比较两种值类型,并将隐式地将它们打包。但是它会分别对每一个进行包装,这意味着即使你给它的同时也会总是返回错误#34;价值对象:
PhysicalEquality
当然,还有另一个不同之处,可归结为个人偏好和易用性。 obj.ReferenceEquals
采用curried风格的参数,可以很好地与类型推断和部分应用程序配合使用。 LanguagePrimitives.PhysicalEquality
采用了tupled风格的参数,这意味着使用它会稍微有点难看。
由于所有这些原因,obj.ReferenceEquals
最好在几乎每种方案中使用,而不是msbuild /p:Configuration=Release /p:OSGroup=Windows_NT /p:Performance=true
。