プログラミングGauche 7.2 手続きを取る手続き 練習問題

プログラミングGaucheの練習問題(p68)を解く。

for-each-numbers

(define (for-each-numbers proc lis)
  (for-each proc (filter number? lis)))

(for-each-numbers print '(1 2 #f 3 4 #t))
gosh> 1
2
3
4
#<undef>

map-numbers

(define (map-numbers proc lis)
  (map proc (filter number? lis)))

(map-numbers (lambda (x) (* x 2)) '(1 2 #f 3 4 #t))
gosh> (2 4 6 8)

numbers-only

(define (numbers-only walker)
  (lambda (proc lis)
          (walker proc (filter number? lis))))

((numbers-only for-each) print '(1 2 #f 3 4 #t))
gosh> 1
2
3
4
#<undef>

((numbers-only map) (lambda (x) (* x 2)) '(1 2 #f 3 4 #t))
gosh> (2 4 6 8)

numbers-only を tree-walk に渡すと、ネストされたリストをたどっていかないために目的を達成できない。

(tree-walk (numbers-only for-each) print '((1 2 #t 3 #f) 4 5 #t #f (6 (7 8 #f))))
gosh> 4
5
#<undef>

手続き filter はフラットなリストにのみ作用するために、ネストされたリストが扱えない。

(filter number? '((1 2 #t 3 #f) 4 5 #t #f (6 (7 8 #f))))
;gosh> (4 5)

walker はリストの各要素に手続きを作用させなければならない。
そこで、入れ子のリストに対して作用する filter-for-tree を作る。

(define (filter-for-tree pred lis)
  (cond ((null? lis) '())
        ((pair? (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-for-tree pred (cdr lis)))))

(filter-for-tree number? '((1 2 #t 3 #f) 4 5 #t #f (6 (7 8 #f))))
gosh> ((1 2 3) 4 5 (6 (7 8)))

filter-for-tree を使って、入れ子になったリストに作用する numbers-only-for-tree を作る。

(define (numbers-only-for-tree walker)
  (lambda (proc lis)
          (walker proc (filter-for-tree number? lis))))

(tree-walk (numbers-only-for-tree for-each) print '((1 2 #t 3 #f) 4 5 #t #f (6 (7 8 #f))))
gosh> 1
2
3
4
5
6
7
8
#<undef>

(tree-walk (numbers-only-for-tree map) (lambda (x) (* x 2)) '((1 2 #t 3 #f) 4 5 #t #f (6 (7 8 #f))))
gosh> ((2 4 6) 8 10 (12 (14 16)))
プログラミングGauche
プログラミングGauche

posted with amazlet at 08.11.14
Kahuaプロジェクト
オライリージャパン
売り上げランキング: 22775
«
»