2016-02-19 7 views
1

Цель состоит в том, чтобы написать функцию фильтра только с одним вызовом foldr без рекурсии или любых других процедур более высокого порядка (map, andmap, apply и т. Д.).пишущий фильтр с помощью одного вызова foldr?

В настоящее время я использую

(define (filter ps xs) 
    (if (empty? xs) 
     ps 
     (foldr (lambda (p y) 
       (if (andmap p xs) 
        (cons p y) 
        y)) 
       '() 
       ps))) 

однако он использует andmap функцию, которая рассматривается процедура высшего порядка

Цель должна иметь

(filter positive? '(-1 2 3 4 -5 -6)) 
=> '(2 3 4) 

с одним вызовом foldr

ответ

3

Я думаю, вы не понимаете, как foldr работает, вы должны передать список для обработки в качестве последнего параметра и для применения фильтра примените ps к каждому элементу, который вы хотите проверить. Лучше попробовать что-то вроде этого:

(define (filter ps xs) 
    (foldr (lambda (p y) 
      (if (ps p) 
       (cons p y) 
       y)) 
     '() 
     xs)) 

Он работает, как ожидалось:

(filter positive? '(-1 2 3 4 -5 -6)) 
=> '(2 3 4) 
+0

Как бы реализовать его таким образом, если ps - это список, состоящий из процедур, так что возвращенный список сохраняет только элемент, который является истинным для всех процедур? Я могу использовать только один вызов foldr. – Chase

+0

Это сложнее, вам нужно будет пройти список процедур в состоянии 'if'. Замените '(ps s)' на '(andmap (lambda (f) (fp)) ps)' –

+0

Ну да, это будет проблемой, я могу использовать только один вызов foldr и ничего другого (не могу использовать andmap и никакой рекурсии), иначе это было бы намного менее запутанным. – Chase

0

Это звучит как домашнее задание. Я могу понять, почему foldr был выбран, но ради видя это реализовано с foldl здесь вы идете

(define (filter f xs) 
    (reverse (foldl (λ (x ys) (if (f x) (cons x ys) ys)) 
        null 
        xs))) 

(filter positive? '(-1 2 3 4 -5 -6)) 
;=> '(2 3 4) 

foldl имеет явное преимущество перед foldr в том, что она осуществляется с соответствующим хвостового вызова.