2

I'm trying to remove duplicates in my streams in scheme R5RS. Here's my code.

(define (remove-duplicates lst)
  (cond ((stream-null?? lst) stream-null?)
        ((not (memq (stream-car lst) (stream-cdr lst)))
         (cons-stream (stream-car lst) (remove-duplicates (stream-cdr lst))))
        (else (remove-duplicates (stream-cdr lst)))))

(define (memq item x)
  (cond ((stream-null?? x) #f)
        ((eq? item (stream-car x)) x)
        (else (memq item (stream-cdr x)))))

I can't see why this doesn't work. Any solutions or help would be appreciated.

1 Answers1

2

"Doesn't work" is a very vague problem description, but I'll try to answer anyway.

memq isn't lazy, and even if it were, you can't test for membership in infinite streams for relatively obvious reasons.

To keep the stream lazy, you can't decide whether an item should be included by looking "forwards", only "backwards" - the future is concealed to you and you can only base your decisions on the past.

You need to turn the problem around - instead of filtering out all instances except the last, you keep the first and filter out the rest, if any turn out to exist when you finally get there.
(In an endless stream, it's easy to remove something once you've found it, but it's impossible to discover that something isn't there.)

stream-filter is useful for filtering, and the result might look something like this:

(define (remove-duplicates lst)
  (if (stream-null? lst)
      stream-null
      (stream-cons (stream-car lst) 
                   (remove-duplicates 
                    (stream-filter (lambda(x) (not (eq? x (stream-car lst)))) 
                                   (stream-cdr lst))))))
molbdnilo
  • 64,751
  • 3
  • 43
  • 82