La solución en las respuestas de Thomas y cago es funcionalmente correcta. Un problema que puede molestarlo si utiliza su solución como está es que obtendrá más colisiones de las esperadas si tiene muchas claves que son iguales para (=)
y diferentes para (==)
. De hecho, todas las claves que son iguales para (=)
tienen el mismo hash para Hashtbl.hash
, y terminan en el mismo depósito, donde se reconocen como diferentes (ya que solicitó (==)
para usarse como función de igualdad) y crean enlaces diferentes. En el peor de los casos, la tabla hash se comportará con la misma complejidad que una lista de asociación (que, dicho sea de paso, es otra estructura de datos que podría estar utilizando, y entonces no tendría que preocuparse de proporcionar una función hash)
Si puede aceptar la clave de un valor que cambia ocasionalmente (y por lo tanto el valor es imposible de recuperar de la tabla hash, ya que el enlace está en el cubo incorrecto), puede usar la siguiente función de bajo nivel como picadillo:
external address_of_value: 'a -> int = "address_of_value"
Implementado en C como:
#include "caml/mlvalues.h"
value address_of_value(value v)
{
return (Val_long(((unsigned long)v)/sizeof(long)));
}
a continuación, utilizar:
module H = Hashtbl.Make(struct
type t = foo
let equal = (==)
let hash = address_of_value
end);;
Este tipo de comparación hash es un poco frágil cuando se usa con valores inmutables, como en su ejemplo. Los documentos dicen que el resultado de (==) depende de la implementación en ese caso: ver el [módulo de Pervasives en ** Comparaciones **] (http://caml.inria.fr/pub/docs/manual-ocaml/libref/ Pervasives.html). En teoría, el compilador o el tiempo de ejecución pueden hacer que dos valores inmutables iguales sean físicamente iguales si lo desean. –
@JeffreyScofield El compilador o el tiempo de ejecución también pueden hacer que los valores que esperaría ser físicamente iguales sean diferentes, y eso no es teórico: 'let test x = let t = Array.make 1 x in x == t. (0) ;; prueba 1.0 ;; 'calcula' falso'. El GC de múltiples hilos para Caml que solo existe en papel también puede duplicar valores inmutables. –
Gracias, estos son ejemplos muy interesantes, aunque creo que OP está más preocupado con la otra cara de la moneda. No puede depender de valores inmutables que tengan identidades físicas únicas (a! = B) a menos que no sean iguales (a <> b). La solución habitual (o la que he usado) es mantener un identificador único en sus valores. Esto también ayuda con el hash, por supuesto. –