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が書けました.