exercise 3.25

調子いい感じ。(・・・問題はこの次な気もするが)
以下解答。

(define (assoc key records)
  (cond ((null? records) #f)
        ((equal? key (caar records)) (car records))
        (else (assoc key (cdr records)))))

(define (make-table)
  (list '*table*))

(define (lookup keys table)
  (let ((subtable (assoc (car keys) (cdr table))))
    (if subtable
        (if (null? (cdr keys))
            (cdr subtable)
            (lookup (cdr keys) subtable))
          #f)))

(define (insert! keys value table)
  (define (make-new-tables keys value)
    (if (null? (cdr keys))
        (cons (car keys) value)
        (list (car keys)
              (make-new-tables (cdr keys) value))))
  (let ((subtable (assoc (car keys) (cdr table))))
    (if subtable
        (if (null? (cdr keys))
            (set-cdr! subtable value)
            (insert! (cdr keys) value subtable))
        (set-cdr! table
                  (cons (make-new-tables keys value)
                        (cdr table)))))
  'ok)

とりあえずlookupはサクッと潰した。
insert!の方はキーが見つからなかった後どうするか考えて、結局めんどいのでmake-new-tablesとか適当な名前の関数を作った。

ちなみに某所の解答例では(パス掛かってたけどコピっていいのかなぁ・・・)

(define (insert! keylist value table)
  (let ((subtable (assoc (car keylist) (cdr table))))
    (if subtable
        (if (null? (cdr keylist))
            (set-cdr! subtable value)
            (insert! (cdr keylist) value subtable))
        (set-cdr! table
                  (cons (if (null? (cdr keylist))
                            (cons (car keylist) value)
                            (let ((newtable (list (car keylist))))
                              (insert! (cdr keylist) value newtable)
                              newtable))
                        (cdr table))))))

とやっていた。確かにnewtableは空だから再帰で渡してもうまいこといくなぁ、と感心した。しかしletの後に式を2つ書くのは何だか慣れない・・・他でもそんな感じだけど。

あとkahuaの方では、ややこしいテーブルを作らずにリストをそのままkeyとして渡してた・・・・。なるほど盲点だなぁ。(というかありなのかな、これ)