f# equality

¿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 .