Как да си направим разрушителен филтър! в схемата?

Мога да накарам филтъра да работи, но не го прави разрушително. По-долу са началният код и тестовите случаи:

(define (filter! f s)
;;Your solution

Тестови случаи:

(define (big x) (> x 5))

(define ints (list 1 10 3 8 4 7)) 
(define ints1 (cdr ints))


(define filtered-ints (filter! big ints))  
filtered-ints 
; expect (10 8 7) 

(eq? filtered-ints ints1) ; expect #t

Може ли някой да помогне, моля?


person hash__x    schedule 24.04.2012    source източник
comment
Искате да кажете, че филтърът ще промени списъка, даден като аргумент, като премахне елементите, които не преминават теста? Каква е ползата от ints1 тук?   -  person PJ.Hades    schedule 24.04.2012
comment
И аз не съм сигурен, но предполагам, че това е нещо, свързано с промяната на указателя в оригиналния входен списък, което прави filtered-ints и ints1 еквивалентни. Това ме обърква най-много.   -  person hash__x    schedule 24.04.2012
comment
възможен дубликат на Направете разрушителен реверс! функция в схема   -  person matt    schedule 24.04.2012
comment
@matt reverse! е доста различен от filter!, това не е дублиран въпрос   -  person Óscar López    schedule 24.04.2012
comment
@ÓscarLópez - о, да. Моя вина. И двете изскочиха заедно и аз бях твърде бърз с бутона за затваряне.   -  person matt    schedule 24.04.2012


Отговори (1)


Това трябва да работи:

(define (filter! f lst)
  (let loop ((ans lst))
    (cond ((null? ans)
           ans)
          ((not (f (car ans)))
           (loop (cdr ans)))
          (else
           (scan-in f ans (cdr ans))
           ans))))

(define (scan-in f prev lst)
  (if (pair? lst)
    (if (f (car lst))
        (scan-in  f lst  (cdr lst))
        (scan-out f prev (cdr lst)))))

(define (scan-out f prev lst)
  (let loop ((lst lst))
    (if (pair? lst)
        (if (f (car lst))
            (begin (set-cdr! prev lst)
                   (scan-in  f lst (cdr lst)))
            (loop (cdr lst)))
        (set-cdr! prev lst))))

Адаптирах горното от filter! процедура в SRFI 1: Списъчна библиотека. Забележете, че ако използвате Racket, нещо или две трябва да бъдат променени, за да може горният код да работи правилно. Например, Racket вече не поддържа set-cdr! и вместо това ще трябва да използвате set-mcdr!.

person Óscar López    schedule 24.04.2012