hashes: support object default hash (#17175)

This commit is contained in:
Timothee Cour
2021-02-25 23:45:37 -08:00
committed by GitHub
parent 4a31088ac2
commit 63f1c38f4e
3 changed files with 62 additions and 18 deletions

View File

@@ -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`.

View File

@@ -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`.

View File

@@ -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()