Physical equality of functions

So… I’ve been trying to understand hash functions better, and so I was passing random stuff into Hashtbl.hash.

Apropos of nothing, I tried passing functions into Hashtbl.hash to see what would happen, and found that some functions produce new hashes every time and some produce the same hash every time, which piqued my curiosity. I noticed I could also observe this by testing a function for physical equality with itself. (Also it’s fun to make ascii robot faces like (+) == (+) in utop.)

I promise I’m not going to use this knowledge for anything (:sweat_smile:), but why are some functions physically equal to themselves and some aren’t? My only guess is that ones that aren’t equal are being inlined on use, but I have no idea.

I think it depends if the function was declared with external or not:

external id1 : 'a -> 'a = "%identity"
let id2 x = x

id1 == id1 is false, but id2 == id2 is true.

2 Likes

Oh interesting. There are more externals than I thought (I’m surprised stuff like |>, @@, ignore, and incr are external). Thanks!

Indeed, externals are not first-class objects in the language and each mention of id1 as a variable it implicitly eta-expanded to fun x -> id1 x causing a fresh allocation.

Cheers,
Nicolas

5 Likes