R6RS Records をサポートしよう その2
R6RS Records の Procedural layer の実装をしている。
現在7割ほど。やっと分かってきたのだが Syntactic layer の屋台骨を Procedural layer が支えている形なのだ。
つまり構造体的なものは Procedural layer だけで実現でき、Syntactic layer はそれを簡便にしてくれるわけ。
構造体は
- 単一継承をサポートしている点
- コンストラクタを柔軟に作れるように protocol をサポートしている点
が実装の難所だろう。
現時点で以下のようなテストが通っている。継承も protocol もある程度は動いているようだ。
(let* ([:point (make-record-type-descriptor 'point #f #f #f #f '#((mutable x) (mutable y)))] [:point-cd (make-record-constructor-descriptor :point #f #f)] [make-point (record-constructor :point-cd)] [point? (record-predicate :point)] [point-x (record-accessor :point 0)] [point-y (record-accessor :point 1)] [point-x-set! (record-mutator :point 0)] [point-y-set! (record-mutator :point 1)] [p1 (make-point 1 2)]) (and (point? p1) (= (point-x p1) 1) (= (point-y p1) 2) (point-x-set! p1 5) (= (point-x p1) 5))) (let* ([:point (make-record-type-descriptor 'point #f #f #f #f '#((mutable x) (mutable y)))] [:point2 (make-record-type-descriptor 'point2 :point #f #f #f '#((mutable x) (mutable y)))] [make-point2 (record-constructor (make-record-constructor-descriptor :point2 #f #f))] [point? (record-predicate :point)] [point-x (record-accessor :point 0)] [point-y (record-accessor :point 1)] [point-x-set! (record-mutator :point 0)] [point-y-set! (record-mutator :point 1)] [point2? (record-predicate :point2)] [point2-xx (record-accessor :point2 0)] [point2-yy (record-accessor :point2 1)] [point2-xx-set! (record-mutator :point2 0)] [point2-yy-set! (record-mutator :point2 1)] [p2 (make-point2 1 2 3 4)]) (and (point? p2) (point2? p2) (= (point-x p2) 1) (= (point-y p2) 2) (= (point2-xx p2) 3) (= (point2-yy p2) 4) (point-x-set! p2 5) (= (point-x p2) 5) (point-y-set! p2 6) (= (point-y p2) 6) (point2-xx-set! p2 7) (= (point2-xx p2) 7) (point2-yy-set! p2 8) (= (point2-yy p2) 8) )) (let* ([:point (make-record-type-descriptor 'point #f #f #f #f '#((mutable x) (mutable y)))] [:point-cd/abs (make-record-constructor-descriptor :point #f (lambda (new) (lambda (x y) (new (abs x) (abs y)))))] [point-x (record-accessor :point 0)] [point-y (record-accessor :point 1)] [make-point/abs (record-constructor :point-cd/abs)]) (and (= (point-x (make-point/abs -1 -2)) 1) (= (point-y (make-point/abs -1 -2)) 2)))