tup+ は2つのタップを引数に取り、それぞれの1番目同士、2番目同士・・・を足し合わせたタップを返す。タップというのは、数のリストのことだ。「数のリストのことをタップ(あるいはタプル)と呼びましょう」と書いてあるから、Scheme の用語というよりこの本(「Scheme手習い」)での用語と考えていいのかな。
同じ長さのタップの場合
とにかく書いてみよう。ただし、まずは2つのタップの長さは同じとする。
(define add1
(lambda (n)
(+ n 1)))
(define sub1
(lambda (n)
(- n 1)))
(define o+
(lambda (n m)
(cond
((zero? m) n)
(else (add1 (o+ n (sub1 m)))))))
(define tup+
(lambda (tup1 tup2)
(cond
((null? tup1) (quote ()))
(else (cons (o+ (car tup1) (car tup2)) (tup+ (cdr tup1) (cdr tup2)))))))
(print (tup+ '(1 2 3) '(4 5 6)))
実行:
^o^ > gosh tupplus.scm (5 7 9)
うまくいったようだ。
でも、答えを見たら、cond のひとつ目の条件(21行目)が (and (null? tup1) (null? tup2)) になっていた。2つのタップの長さが同じという前提なんだから片方だけチェックすればいいと思うんだけどな。
違う長さのタップの場合
(define add1
(lambda (n)
(+ n 1)))
(define sub1
(lambda (n)
(- n 1)))
(define o+
(lambda (n m)
(cond
((zero? m) n)
(else (add1 (o+ n (sub1 m)))))))
(define tup+
(lambda (tup1 tup2)
(cond
((null? tup1) tup2)
((null? tup2) tup1)
(else (cons (o+ (car tup1) (car tup2)) (tup+ (cdr tup1) (cdr tup2)))))))
(print (tup+ '(1 2 3) '(10 20 30)))
(print (tup+ '(1 2 3) '(10 20 30 40 50)))
(print (tup+ '(1 2 3 4 5) '(10 20 30)))
実行:
^o^ > gosh tupplus2.scm (11 22 33) (11 22 33 40 50) (11 22 33 4 5)
うまくいった。ポイントは21行目と22行目だ。tup1 と tup2 のどちらかが先に 空になったら、もう一方のタップを返して終了する。もちろん、両方が同時に空になった場合(つまり同じ長さの場合)には (null? tup1) の値 tup2 も空だから、これでうまくいくわけだ。