2015/09/20
プログラミング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
が書けました.