ppb / ppb-vector

A 2D Vector class for PPB.
Artistic License 2.0
2 stars 18 forks source link

Make Vector hashable #174

Closed AstraLuma closed 3 years ago

AstraLuma commented 5 years ago

Allow Vector to be used as dictionary keys.

While I don't expect to do much indexing by Vector, this is useful if you want to map Vector -> value for some reason (eg, in ppb-oneko, mapping directional vectors to their animation).

nbraud commented 5 years ago

@astronouth7303 We discussed in a previous PR that the current API for Vector cannot implement the hash protocol because hash(vector) == hash(vector_like) would need to hold whenever vector == vector_like.

It might be possible to work our way around that, if (and only if) tuple is the only VectorLike type that is hashable; if so, we “just” need to guarantee that hash(v) == hash((v.x, v.y)).

nbraud commented 5 years ago

Update: this is not the case, frozendict({"x": 0, "y": 1}) is also an hashable vector-like, with an incompatible hash.

AstraLuma commented 5 years ago

This is the point where I wish python had "semantically equal" or "equal enough" vs "exactly equal".

For cases where users would want ==, we'd want "semantically equal" (that is, they carry the same abstract vector idea, even if the specific data structures differ).

For dictionaries and uses involving hash(), we'd want "exactly equal", where "this is the same value", right?

Practically, you'd expect immutable values to be usable as dictionary keys. But for us, that's a can of worms.

pathunstrom commented 5 years ago

I mean, I'd find it very surprising for a tuple(0, 1) to hash to the same thing as Vector(0, 1) but that might just be experience with Python and not genuinely reasonable logic.

AstraLuma commented 5 years ago

Properly implementing __hash__() from scratch is surprisingly tricky, so a quick (and probably not unreasonable) implementation would be hash((x, y)), or just use the hash of the tuple.

Doing something like hash(('Vector', x, y)) might work? but there's the bigger problem that "Do vector-likes count for dictionary keys?"

nbraud commented 5 years ago

@pathunstrom The protocol for hash() specifies that property must hold. I wrote tests that show we can't currently comply with that protocol.

Also, it would be very surprising to have t[x] != t[y] when x == y (if t is any sort of container that uses hashes), and violating the hash invariant might even cause the container to throw an exception or fail in worse ways (uncatchable assertion failure from C, segfault, ...)

nbraud commented 5 years ago

so a quick (and probably not unreasonable) implementation would be hash((x, y))

@astronouth7303 dataclass' automatic hash implementation is seemingly equivalent to that, it's not the actual problem.

nbraud commented 3 years ago

Closing, as this is impossible to do in a spec-compliant way.