mapの実装
演習問題4.14が,mapに関する問題だった.
問題の内容は
Aさん,Bさんはそれぞれ超循環評価器の実験をしていた.Aさんは,mapの定義を入力し,それを使うテストプログラムをいくつか走らせたところ,うまく動いた.ところで,Bさんは,システムの組み込みのmapを基本手続きとして組み込んだ.Bさんのテストプログラムはうまく動かない.なぜか?
という感じ.
おそらく,<手続き>が属するクラス(評価器の場合はtag)がもともとの実装のものと,ここの評価器では違うから.
実際やってみると確かにうまく動かない.
ところで,mapの1引数のものはいつだかの演習で実装したのは覚えているけれど,複数の引数をとる場合は実装したっけ?と思い,mapを実装してみた.かなり微妙になった.
;1引数用 (define (map-for-one-argument proc arg) (if (null? arg) '() (cons (proc (car arg)) (map-for-one-argument proc (cdr arg))))) (define (my-map proc . args) (cond [(null? args) '()] [(= (length args) 1) (map-for-one-argument proc (car args))] [else (let ((cdr-args (map-for-one-argument cdr args))) (if (equal? cdr-args '(() ())) (set-cdr! cdr-args ())) (cons (apply proc (map-for-one-argument car args)) (apply my-map (cons proc cdr-args))))]))
なぜ
(let ((cdr-args (map-for-one-argument cdr args))) (if (equal? cdr-args '(() ())) (set-cdr! cdr-args ()))
を入れたかというと,再起呼び出し後,(null? args)で戻ってくると,
(cons (apply proc (map-for-one-argument car args)) (apply my-map (cons proc cdr-args))))]))
の2つ目のapplyが
(apply my-map (proc () ()))
となり,applyができないので,
(apply my-map (proc ())
となるようにするため.
しかし,気持ちわるいな.なんとかならないのか.