¿Cómo compruebo la igualdad de referencia en F#?
equality (1)
F # usa la igualdad estructural para el operador =
, que es casi siempre lo que quieres:
let a = [1; 2; 3]
let b = [1; 2; 3]
printfn "%A" (a = b) // Prints "true"
Pero en algunos algoritmos, puede ser importante poder preguntar "¿Son estas dos cosas el mismo objeto ?" Esto puede ayudar a detectar ciclos en una gráfica, por ejemplo. Entonces, ¿cómo pido la igualdad de referencia en F #? Es decir, ¿cómo escribo la función isSameObject
continuación?
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"
La respuesta, resulta que es usar 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"
Precisamente una pregunta que pude encontrar en fue la siguiente: ¿ verificación de igualdad corta en F #? Y dado que el tema de esa pregunta casi me hizo echar un vistazo, pensé que iba a hacer (y responder) la pregunta de nuevo. Es de esperar que la línea de asunto de esta pregunta facilite la búsqueda cuando busque en Google términos como "igualdad referencial en F #".
¿Qué pasa con obj.ReferenceEquals
?
En un comentario, Fyodor Soikin pregunta qué está mal con obj.ReferenceEquals
. La respuesta es "no mucho", pero hay dos formas en que LanguagePrimitives.PhysicalEquality
es mejor que obj.ReferenceEquals
para la mayoría de los códigos F #:
1) PhysicalEquality
lanza un error de compilación cuando le pasas dos tipos diferentes, mientras que obj.ReferenceEquals
solo toma dos obj
s y, por lo tanto, trata de comparar una int list
con una char 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
no le permitirá comparar tipos de valor, solo tipos de referencia. obj.ReferenceEquals
le permitirá comparar dos tipos de valores y los encajonará implícitamente en primer lugar. Pero encaja cada uno por separado, lo que significa que siempre devolverá el valor falso incluso cuando le asignó el "mismo" objeto de valor:
let n = 3
let n'' = n
obj.ReferenceEquals(n,n'') // Returns false!
LanguagePrimitives.PhysicalEquality n n'' // Compiler error
Y, por supuesto, hay otra diferencia, que se reduce a las preferencias personales y la facilidad de uso. PhysicalEquality
toma parámetros de estilo curry, que funcionan bien con inferencia de tipos y aplicación parcial. obj.ReferenceEquals
toma parámetros de estilo tupleados, lo que significa que es un poco más difícil de usar.
Por todas estas razones, LanguagePrimitives.PhysicalEquality
es mejor usar, en casi todos los escenarios, que obj.ReferenceEquals
.