プログラミングGauche 7.2練習問題
- for-each-numbersを書く
(define for-each-numbers (lambda (proc lis) (for-each proc (filter number? lis))))
- map-numbersを書く
(define map-number (lambda (proc lis) (map proc (filter number? lis))))
- numbers-onlyを書く
(define (numbers-only walker) (lambda (proc lis) (walker proc (filter number? lis))))
- 「数値とそれ以外が混じっている入れ子のリスト」の数値だけについて
(numbers-only for-each)
や(numbers-only map)
をtree-walk
に渡して処理ができるか.できないならなぜできないか.
tree-walk
のコードは以下の通り
(define (tree-walk walker proc tree) (walker (lambda (elt) (if (list? elt) (tree-walk walker proc elt) (proc elt))) tree))
以下を例に考えてみた.
(tree-walk (numbers-only map) print '(1 2 (3 (#f 4)) (#t 5)))
実行結果は
1 2 (#<undef> #<undef>)
入れ子になった部分の処理が出来ていない.
numbers-only
とtree-walk
にリストがどう渡されているのか調べてみる.
(define (tree-walk walker proc tree) (walker (lambda (elt) (if (list? #?=elt) (tree-walk walker proc elt) (proc elt))) tree)) (define (numbers-only walker) (lambda (proc lis) (walker proc #?=(filter number? lis)))) (tree-walk (numbers-only map) print '(1 2 (3 (#f 4)) (#t 5)))
結果は
#?="(standard input)":262:(filter number? lis) #?- (1 2) #?=elt #?- 1 1 #?=elt #?- 2 2 (#<undef> #<undef>)
これを見るとtree-walk
にリストが渡される前にnumbers-only
のfilter
が先に評価されている.
ここを改善して入れ子に対応したfilter
を書いて,numbers-only-for-tree
を書く.
(car lis)
がリストならそこに再帰してfilter
をかける.
(define filter-for-tree (lambda (pred lis) (cond ((null? lis) '()) ((list? (car lis)) (cons (filter-for-tree pred (car lis)) (filter-for-tree pred (cdr lis)))) ((pred (car lis)) (cons (car lis) (filter-for-tree pred (cdr lis)))) (else (filter pred (cdr lis)))))) (define (numbers-only-for-tree walker) (lambda (proc lis) (walker proc (filter-for-tree number? lis))))
numbers-only
と同じように実行してみます.
gosh> (tree-walk (numbers-only-for-tree map) print '(1 2 (3 (#f 4)) (#t 5))) 1 2 3 4 5 (#<undef> #<undef> (#<undef> (#<undef>)) (#<undef>))
入れ子なったリストに対応したnumbers-only-for-map
が書けました.