; a dozen lines of code

(define (make-hash hash eql? size)
  (let ((hash-table (make-vector size (list))))
    (case-lambda
      ((lookup key)
        (let ((idx (modulo (hash key) size)))
          (let loop ((bucket (vector-ref hash-table idx)))
            (cond ((null? bucket) bucket)
                  ((eql? (caar bucket) key) (car bucket))
                  (else (loop (cdr bucket)))))))
      ((install key value)
        (let ((idx (modulo (hash key) size)))
          (let loop ((bucket (vector-ref hash-table idx)) (new-bucket (list)))
            (cond ((null? bucket)
                    (vector-set! hash-table idx (cons (cons key value) new-bucket)))
                  ((eql? (caar bucket) key)
                    (vector-set! hash-table idx
                      (append (cons (cons key value) (cdr bucket)) new-bucket)))
                  (else (loop (cdr bucket) (cons (car bucket) new-bucket)))))))
      (else (error 'hash-table "unrecognized command")))))

(define (string-hash str)
  (do ((i 0 (+ i 1))
       (h 0 (+ (* h 31) (char->integer (string-ref str i)))))
    ((= (string-length str) i) h)))

(define h (make-hash string-hash string=? 17))
(h 'put "alfa" 1)
(h 'put "bravo" 2)
(h 'put "charlie" 3)
(display (h 'get "alfa")) (newline)
(h 'put "alfa" 13)
(display (h 'get "alfa")) (newline)