読者です 読者をやめる 読者になる 読者になる

(wat-aro)

無職から有職者にランクアップしました

プログラミングGauche 7.2練習問題

scheme gauche
  • 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-onlytree-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-onlyfilterが先に評価されている.
ここを改善して入れ子に対応した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が書けました.