diff options
author | Timothee Cour <timothee.cour2@gmail.com> | 2021-02-25 23:45:37 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-26 08:45:37 +0100 |
commit | 63f1c38f4e0c6f8700a8877d5f3f6f2ac0fc16e6 (patch) | |
tree | 612126ea34cda446ff65ea6c7580d8afa324b091 | |
parent | 4a31088ac29b6cc889d2c69e56f4aab72d8223de (diff) | |
download | Nim-63f1c38f4e0c6f8700a8877d5f3f6f2ac0fc16e6.tar.gz |
hashes: support object default hash (#17175)
-rw-r--r-- | changelog.md | 4 | ||||
-rw-r--r-- | lib/pure/hashes.nim | 30 | ||||
-rw-r--r-- | tests/stdlib/thashes.nim | 46 |
3 files changed, 62 insertions, 18 deletions
diff --git a/changelog.md b/changelog.md index 6b2c412f0..db5b3c14b 100644 --- a/changelog.md +++ b/changelog.md @@ -173,14 +173,16 @@ provided by the operating system. dumping (on select signals) and notifying the parent process about the cause of termination. -- Added `strip` and `setSlice` to `std/strbasics`. +- `hashes.hash` now supports `object`, but can be overloaded. +- Added `strip` and `setSlice` to `std/strbasics`. - Added to `wrapnils` an option-like API via `??.`, `isSome`, `get`. - `std/options` changed `$some(3)` to `"some(3)"` instead of `"Some(3)"` and `$none(int)` to `"none(int)"` instead of `"None[int]"`. + ## Language changes - `nimscript` now handles `except Exception as e`. diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 54e083d25..c526c976f 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -54,20 +54,6 @@ runnableExamples: ## **Note:** If the type has a `==` operator, the following must hold: ## If two values compare equal, their hashes must also be equal. ## -## You can hash an object by all of its fields with the `fields` iterator: -runnableExamples: - proc hash(x: object): Hash = - for f in fields(x): - result = result !& hash(f) - result = !$result - - type - Obj = object - x: int - y: string - - doAssert hash(Obj(x: 520, y: "Nim")) != hash(Obj(x: 520, y: "Nim2")) - ## See also ## ======== ## * `md5 module <md5.html>`_ for the MD5 checksum algorithm @@ -499,14 +485,24 @@ proc hashIgnoreCase*(sBuf: string, sPos, ePos: int): Hash = result = !$h -proc hash*[T: tuple](x: T): Hash = - ## Efficient hashing of tuples. +proc hash*[T: tuple | object](x: T): Hash = + ## Efficient hashing of tuples and objects. ## There must be a `hash` proc defined for each of the field types. + runnableExamples: + type Obj = object + x: int + y: string + type Obj2[T] = object + x: int + y: string + assert hash(Obj(x: 520, y: "Nim")) != hash(Obj(x: 520, y: "Nim2")) + # you can define custom hashes for objects (even if they're generic): + proc hash(a: Obj2): Hash = hash((a.x)) + assert hash(Obj2[float](x: 520, y: "Nim")) == hash(Obj2[float](x: 520, y: "Nim2")) for f in fields(x): result = result !& hash(f) result = !$result - proc hash*[A](x: openArray[A]): Hash = ## Efficient hashing of arrays and sequences. ## There must be a `hash` proc defined for the element type `A`. diff --git a/tests/stdlib/thashes.nim b/tests/stdlib/thashes.nim index ce7bb7d8c..a4487c8c0 100644 --- a/tests/stdlib/thashes.nim +++ b/tests/stdlib/thashes.nim @@ -130,5 +130,51 @@ proc main() = # run at CT, expecting c semantics. discard + block: # hash(object) + type + Obj = object + x: int + y: string + Obj2[T] = object + x: int + y: string + Obj3 = object + x: int + y: string + Obj4 = object + case t: bool + of false: + x: int + of true: + y: int + z: int + Obj5 = object + case t: bool + of false: + x: int + of true: + y: int + z: int + + proc hash(a: Obj2): Hash = hash(a.x) + proc hash(a: Obj3): Hash = hash((a.x,)) + proc hash(a: Obj5): Hash = + case a.t + of false: hash(a.x) + of true: hash(a.y) + + doAssert hash(Obj(x: 520, y: "Nim")) != hash(Obj(x: 520, y: "Nim2")) + doAssert hash(Obj2[float](x: 520, y: "Nim")) == hash(Obj2[float](x: 520, y: "Nim2")) + doAssert hash(Obj2[float](x: 520, y: "Nim")) != hash(Obj2[float](x: 521, y: "Nim2")) + doAssert hash(Obj3(x: 520, y: "Nim")) == hash(Obj3(x: 520, y: "Nim2")) + + doAssert hash(Obj4(t: false, x: 1)) == hash(Obj4(t: false, x: 1)) + doAssert hash(Obj4(t: false, x: 1)) != hash(Obj4(t: false, x: 2)) + doAssert hash(Obj4(t: false, x: 1)) != hash(Obj4(t: true, y: 1)) + + doAssert hash(Obj5(t: false, x: 1)) != hash(Obj5(t: false, x: 2)) + doAssert hash(Obj5(t: false, x: 1)) == hash(Obj5(t: true, y: 1)) + doAssert hash(Obj5(t: false, x: 1)) != hash(Obj5(t: true, y: 2)) + static: main() main() |