これを試して:
(define (deep-filter f lst)
(cond
((null? lst) '())
((and (atom? lst) (f lst)) (list lst))
((atom? lst) '())
(else (append (deep-filter f (car lst))
(deep-filter f (cdr lst))))))
これはリストの平坦化と呼ばれ、リスト内の単一の要素 ( の 2 番目のケース) のappend
代わりに使用してパックするというトリックです。これにより、すべてのサブリストが削除され、述語を満たす要素のみが返されることに注意してください。cons
cond
空のリストを削除した後にリスト構造を保持する必要がある場合は、代わりに次のようにします。
(define (deep-filter f lst)
(cond ((null? lst)
'())
((atom? (car lst))
(if (f (car lst))
(cons (car lst) (deep-filter f (cdr lst)))
(deep-filter f (cdr lst))))
(else
(filter (compose not null?)
(cons (deep-filter f (car lst))
(deep-filter f (cdr lst)))))))
これで期待どおりに動作します:
(deep-filter number? '(2 (a ((c)) (b)) 6))
=> '(2 6)
(deep-filter number? '(2 (a ((c)) (1)) 6))
=>'(2 ((1)) 6)
(deep-filter number? '(2 (a ((4)) (1)) 6))
=> '(2 (((4)) (1)) 6)
(deep-filter number? '(2 (a ((4)) (1)) 6 ((((((b))))))))
=> '(2 (((4)) (1)) 6)