第192回 素人くさいSICP読書会(at 三田某所)

  • 会場提供ありがとうございました
  • 参加は最小構成人数の2人
  • 6月の第1週は海外にいる可能性があるので、その場合は読書会は休みにしようという話
  • ○○ったーが流行っているという話から血液型の性格分類はひどいねという話に
  • 問題5.22
  • 非破壊的な方はfactとほとんど同じ。factをちょこちょこっと書き換えたら動いた
(define append-machine
  (make-machine
   '(x y val continue)
   (list (list 'null? null?) (list 'cons cons) (list 'car car) (list 'cdr cdr))
    '((assign continue (label append-done))
    append-loop
      (test (op null?) (reg x))
      (branch (label base-case))
      (save continue)
      (save x)
      (assign x (op cdr) (reg x))
      (assign continue (label after-append))
      (goto (label append-loop))
    after-append
      (restore x)
      (restore continue)
      (assign x (op car) (reg x))
      (assign val (op cons) (reg x) (reg val))
      (goto (reg continue))
    base-case
      (assign val (reg y))
      (goto (reg continue))
    append-done)))
  • 破壊的なほうは、最初、5.11と同じように単純なループにしてはまった
  • それだとcdrで削ったところが復元できない。ということで、valを介する形に書き直し
  • 書けたんだけど、最後の要素とyをappendしたものからxを復元するにはどうしたらいいかがわからなくてタイムアップ
  • で帰り道に考えてたら、ほとんど正解してたことに気付いた
  • set-cdr! val yした時点で、答えはxに入ってる
  • 何のためにxを復元したんだか。アホだオレ
(define append!-machine
  (make-machine
   '(x y temp val continue)
   (list (list 'null? null?) (list 'cdr cdr) (list 'set-cdr! set-cdr!))
    '((assign continue (label last-pair-done))
    last-pair-loop
      (assign temp (op cdr) (reg x))
      (test (op null?) (reg temp))
      (branch (label base-case))
      (save continue)
      (save x)
      (assign x (op cdr) (reg x))
      (assign continue (label after-last-pair))
      (goto (label last-pair-loop))
   after-last-pair
      (restore x)
      (restore continue)
      (goto (reg continue))
   base-case
      (assign val (reg x))
      (goto (reg continue))
   last-pair-done
      (perform (op set-cdr!) (reg val) (reg y)))))

(define (test-append!-machine)
  (set-register-contents! append!-machine 'x '(a b c))
  (set-register-contents! append!-machine 'y '(x y))
  (start append!-machine)
  (get-register-contents append!-machine 'x))

;;(test-append!-machine) => (a b c x y)
  • 何が起きてたのか把握したので、単純ループに書き換えた
  • たぶんこっちが正解
(define append!-machine
  (make-machine
   '(x y temp x-last)
   (list (list 'null? null?) (list 'cdr cdr) (list 'set-cdr! set-cdr!))
    '((assign x-last (reg x))
    last-pair-loop
      (assign temp (op cdr) (reg x-last))
      (test (op null?) (reg temp))
      (branch (label last-pair-done))
      (assign x-last (op cdr) (reg x-last))
      (goto (label last-pair-loop))
   last-pair-done
      (perform (op set-cdr!) (reg x-last) (reg y)))))
  • ということで問題5.22 done