Skip to content

fix: make Number hashable so it works in sets and dict keys#20

Merged
hozblok merged 2 commits into
masterfrom
fix/06-number-hashable
May 16, 2026
Merged

fix: make Number hashable so it works in sets and dict keys#20
hozblok merged 2 commits into
masterfrom
fix/06-number-hashable

Conversation

@hozblok

@hozblok hozblok commented May 11, 2026

Copy link
Copy Markdown
Owner

Problem. Python silently sets __hash__ = None on any class that overrides __eq__ without defining __hash__. Number had __eq__ but no __hash__, so {Number("1"), Number("2")} raised TypeError: unhashable type: 'Number' — and Number couldn't be a dict key or an lru_cache argument either.

Fix. src/formula/formula.py — add __hash__ that hashes the canonical fixed-point string at the configured precision. Two Number instances that compare equal via __eq__ share that canonical form, satisfying Python's a == b ⇒ hash(a) == hash(b) contract.

Test. New file tests/test_number_hashable.py covers set deduplication, dict-key lookup, and the hash/eq agreement for equivalent forms like Number("1") and Number("1.0"). All pass; full suite 320/320.

Defining __eq__ without __hash__ silently sets __hash__ = None on the
class — that left Number unusable as a set member, dict key, or
lru_cache argument. The new __hash__ uses the canonical fixed-point
string at the configured precision so it agrees with __eq__: two
Numbers that compare equal share that formatted form.

Regression test in tests/test_number_hashable.py exercises set
deduplication, dict-key lookup, and the a == b → hash(a) == hash(b)
contract for equivalent forms like Number("1") and Number("1.0").

See ai/improvements_2026-05-09.md item #6.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hozblok hozblok marked this pull request as ready for review May 16, 2026 21:37
@hozblok hozblok merged commit 683bffa into master May 16, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant