(setq h (hash/new
          '(key . value)
          '(1 . 2)
          '("string" . 3)
          '(3 . 4)))

(assert (= 'value (hash/get h 'key)))
(assert (= 2 (hash/get h 1)))
(assert (= 100 (hash/get h 0 100)))
(assert (= NIL (hash/get h 0)))

(hash/map! (lambda (_ v) v) h)
(assert (= 'value (hash/get h 'key)))
(assert (= 2 (hash/get h 1)))
(assert (= 100 (hash/get h 0 100)))
(assert (= NIL (hash/get h 0)))

(hash/remove! h 'key)
(assert (= NIL (hash/get h 'key)))

(hash/map! (lambda (_ v) (+ v 100)) h)
(assert (= 102 (hash/get h 1)))
(assert (= 103 (hash/get h "string")))
(assert (= 100 (hash/get h 0 100)))
(assert (= NIL (hash/get h 0)))

(setq hl (hash->list h))
(assert (= '(3 . 104) (find (lambda (a) (= (car a) 3)) hl)))
(assert (= '("string" . 103) (find (lambda (a) (= (car a) "string")) hl)))
(assert (= '(1 . 102) (find (lambda (a) (= (car a) 1)) hl)))

(setq sum-1 0)
(hash/for-each (lambda (_ v) (setq sum-1 (+ sum-1 v))) h)
(setq sum-2 (hash/fold 0 (lambda (a _ v) (+ a v)) h))
(assert (= sum-1 sum-2 309))

(hash/filter! (lambda (k _) (/= k "string")) h)
;; Hash equality
(assert (= h (hash/new '(1 . 102) '(3 . 104))))
(assert (=
          (hash/new '(1 . 2) '(2 . 3) '("string" . "value"))
          (list->hash '((2 . 3) ("string" . "value") (1 . 2)))
          ))

;; hash->list->hash idempotence
(setq h (hash/new))
(let (i 0)
  (while (< i 10000)
    (hash/put! h (+ "key" i) (+ "value" i))
    (setq i (+ i 1))
    ))
(assert (= h (list->hash (hash->list h))))
