Schemeで身長と体重を記録するプログラムを書いてみた

今日は、Schemeの変数周辺を試してみる。自分用の備忘録。
SICPの3.1節のdispatchを参考にして実験しているのだが、Schemeの(局所)変数は、Cの変数よりもむしろC++のクラスに近い気がする。

(ものすごくざっくりした言い方だが)かっこで囲んだ部分がどんどん内部環境になっていくScheme。内部に登録した局所変数の値を取り出すだけでも、手続きを用意しなければいけない。

次のheight-weight-dataは、SICPの3.1節のmake-accountをまねして、さらに単純化した例である。これは身長と体重を記録するためのプログラムだ。

(define (height-weight-data name height weight)
  (define (dispatch m)
    (cond ((eq? m 'name) name)
	  ((eq? m 'height) height)
	  ((eq? m 'weight) weight)))
  dispatch)

a1にtaro、a2にjiroのデータを入力してみる。

(define a1 (height-weight-data 'taro 170 70))
=>a1

(define a2 (height-weight-data 'jiro 190 100))
=>a2

このようにa1,a2を定義すると、a1とa2は、データ構造は同じであるが、全く別のデータを持つ。

(a1 'name)
=>taro

(a1 'height)
=>170

(a1 'weight)
=>70


(a2 'name)
=>jiro

(a2 'height)
=>190

(a2 'weight)
=>100

(> (a1 'height) (a2 'height))
=>#f


身長、体重を更新できるようにしたのが、以下のheight-weight-dataだ。

(define (height-weight-data name height weight)
  (define (renew-height new-height)
    (set! height new-height)
    height)
  (define (renew-weight new-weight)
    (set! weight new-weight)
    weight)
  (define (dispatch m)
    (cond ((eq? m 'name) name)
	  ((eq? m 'height) height)
	  ((eq? m 'weight) weight)
	  ((eq? m 'renew-height) renew-height)
	  ((eq? m 'renew-weight) renew-weight)))
  dispatch)

(define a1 (height-weight-data 'taro 170 70))
=>a1

(define a2 (height-weight-data 'jiro 190 100))
=>a2

((a1 'renew-height) 172)
=>172
((a1 'renew-weight) 73)
=>73

(a1 'height)
=>172
(a1 'weight)
=>73
(a2 'height)
=>190
(a2 'weight)
=>100

この例では、プログラマの意図通り、taroとjiroの身長、体重を別々に扱えている。SICPの受け売りではあるが、こういった感じで、Schemeはデータをかなり直感的にわかりやすい形で、記録、更新できる。