Skip to content

Commit

Permalink
hashes: support object default hash
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheecour committed Feb 26, 2021
1 parent b725e0e commit 13d65c5
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 18 deletions.
4 changes: 3 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
30 changes: 13 additions & 17 deletions lib/pure/hashes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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`.
Expand Down
46 changes: 46 additions & 0 deletions tests/stdlib/thashes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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()

0 comments on commit 13d65c5

Please sign in to comment.