En Rust, los traits PartialEq y Eq surgen de la filosofía de la seguridad de tipos: todas las operaciones fundamentales para colecciones (HashMap, HashSet) se basan en una definición rigurosa de igualdad. Los traits determinan si los objetos de dos tipos pueden ser comparados usando == y si el tipo se compromete a implementar la "igualdad total" (Eq) o la "igualdad parcial" (PartialEq).
Una implementación incorrecta de PartialEq/Eq lleva a un mal funcionamiento de las colecciones, donde se violan propiedades matemáticas básicas: la comparación consigo mismo, simetría, transitividad. Además, un Eq incorrecto puede hacer que los objetos "se pierdan" en las colecciones o que aparezcan duplicados inesperados.
PartialEq se implementa para tipos en los que la comparación no es posible para todos los valores (por ejemplo, f32, donde NaN != NaN). Eq está destinado solo para relaciones "estrictas" (totales). Los tipos de usuario deben implementar la comparación de acuerdo con estos contratos estrictamente.
Ejemplo de código:
#[derive(PartialEq, Eq)] struct Point { x: i32, y: i32, } let p1 = Point { x: 1, y: 2 }; let p2 = Point { x: 1, y: 2 }; assert!(p1 == p2); // true
Características clave:
¿Por qué para el tipo f32 la biblioteca estándar solo implementa PartialEq y no Eq?
Porque según IEEE-754, NaN != NaN, es decir, la propiedad x == x para todos x no se cumple, y esta es una propiedad necesaria para Eq.
¿Es obligatorio implementar Eq explícitamente si se ha implementado PartialEq manualmente?
Sí, si el tipo soporta igualdad total (x == x siempre true), es necesario implementar Eq manualmente, de lo contrario, algunas estructuras dejarán de compilarse con tu tipo.
¿Puede un usuario implementar PartialEq de manera "asimétrica" (x == y, pero y != x)?
Técnicamente sí, pero esto lleva a un mal funcionamiento de las colecciones y se considera un error.
** Caso negativo
El usuario implementó PartialEq para un tipo que solo compara un campo, ignorando los demás. Como resultado, HashSet "pierde" duplicados.
Ventajas:
Desventajas:
**Caso positivo
Utiliza #[derive(PartialEq, Eq)] o implementa su propia versión de comparación, teniendo en cuenta toda la lógica empresarial, garantizando las propiedades requeridas.
Ventajas:
Desventajas: