Reasoned Schemer (29) 普通に書いてみる
これって関係プログラミングで書いてて何がいいんだろう、ということで
普通に書いてみて、比較しようと思います
まずは足し算まで
(define (bit-xor x y)
(cond
((and (= x 0) (= y 0)) 0)
((and (= x 0) (= y 1)) 1)
((and (= x 1) (= y 0)) 1)
((and (= x 1) (= y 1)) 0)))
(define (bit-and x y)
(cond
((and (= x 0) (= y 0)) 0)
((and (= x 0) (= y 1)) 0)
((and (= x 1) (= y 0)) 0)
((and (= x 1) (= y 1)) 1)))
(define (half-adder x y)
(values (bit-xor x y) (bit-and x y)))
(define (full-adder b x y)
(let*-values (((w xy) (half-adder x y))
((r wz) (half-adder w b))
((c) (bit-xor xy wz)))
(values r c)))
(define (build-num n)
(cond
((zero? n) '())
((even? n) (cons 0 (build-num (/ n 2))))
((odd? n) (cons 1 (build-num (/ (- n 1) 2))))))
(define (get-num n)
(cond
((null? n) 0)
((= (car n) 0) (* 2 (get-num (cdr n))))
((= (car n) 1) (+ 1 (* 2 (get-num (cdr n)))))))
(define (adder b n m)
(cond
((and (= b 0) (null? m)) n)
((and (= b 0) (null? n)) m)
((and (= b 1) (null? m)) (adder 0 n '(1)))
((and (= b 1) (null? n)) (adder 0 '(1) m))
((and (equal? n '(1)) (equal? m '(1)))
(let-values
(((a c) (full-adder b 1 1)))
`(,a ,c)))
(else (gen-adder b n m))))
(define (gen-adder b n m)
(let*-values
(((c e) (full-adder b (car n) (car m)))
((z) (adder e (cdr n) (cdr m))))
(cons c z)))
(define (add n m)
(adder 0 n m))
ここまではほとんどそのまま書けてます
一部場合分け端折ってますが
普通に書くと多値を返すようなところが関係だとなんにも意識しないで書けるっていうのはいいところですね
その代りあれもこれも全部変数にする必要がありますが
(といってもこれはこの処理系特有の事情かもしれない)
次は引き算ですがこれはそのままとはいきません