sl-sh-dev/sl-sh

Hash and Eq traits for Value and Float

Opened this issue · 2 comments

Background

We would like to be able to hash an slvm::Value.
Float is one of the variants of Value so our Float has to also implement Eq and Hash for Value to be hashable.
primitive floats don't implement Eq because NaN != NaN, which also prevents them from implementing Hash.
General programming consensus is to avoid hashing floats because float values that 'feel' like they are equal won't hash to the same value if they are just very close like 4.00000000000000 and 4.000000000000001.
Reference Previous discussion from the F56 PR if necessary

Option 0

give up on hashing Values

Option 1

Have Float pretend to implement Eq and Hash, but prevent any Float hashing.
This allows Float to behave like a primitive where NaN != NaN and 4.00000000000000 != 4.000000000000001
And it allows Value to implement Hash and Eq
We just have to make sure we never actually try to hash our Float. We can enforce this with lisp errors or rust panicking.

Option 2

Have Float legitimately implement Eq and Hash
Float behavior may surprise you with NaN == NaN and equality rounds to nearest multiple of F56::EPSILON.
Note that you can still have two numbers right next to each other that aren't equal because they are halfway between two of these multiples.
This nonstandard behavior won't affect the vm instructions if we modify is_equal_pair in vm.rs
Allow Value to implement Hash and Eq

I'm sure I missed some things so just let me know and I'll try to edit the original post to keep it organized.

related:

#129

and this discussion here:
#123 (comment)