Question

I'm using R5RS Scheme and I just want to implement a function that returns the intersection of two given lists, but I can't do that because I cannot add an element to a list. Here is my code. How can I fix it? I'm really a beginner in Scheme - this is my first work using Scheme.

thx in advance..

(define list3 '())
(define (E7 list1 list2)

        (cond
          ((null? list1)
          list3)
          ((member (car list1) list2) (append list3 (list (car list1))))

        )
  (cond
          ((null? list1)
          list3)
          ((not(null? list1)) (E7 (cdr list1) list2)

        )

     )


)
(E7 '(4 5) '(3 4))
Was it helpful?

Solution

Here is a recursive version that does the intersection instead of the union.

(define (intersect list1 list2)
  (cond ((null? list1)   list1)
        ((member (car list1) list2)   (cons (car list1) (intersect (cdr list1) list2)))
        (t   (intersect (cdr list1) list2))))

OTHER TIPS

I think I see your problem. There are two ways to add an element to a list.

The first way would be actually adding it:

(define (intersect list1 list2)
  (define newlist list2)
  (do ((iter1 list1 (cdr iter1)))
    (not (null? iter1))
    (if (not (member (car iter1) newlist))
        (set! newlist (cons (car iter1) newlist)))))

(You'll probably have to look up the definition of do if you really want to use this.)

You may notice that that's quite ugly. That's because no one actually does it this way. Instead, you have to realize that calling a function creates a new variable as well. Try this:

(define (intersect list1 list2)
  (cond ((null? list1) list2)
        ((member (car list1) list2) (intersect (cdr list1) list2))
        (else (intersect (cdr list1) (cons (car list1) list2)))))

If you're familiar with algorithms, you'll notice that the code I just wrote is quite slow, but it illustrates the point: in each case, you do a little bit of work and then call your function again. If you're having trouble seeing why this works, run this function instead on your example:

(define (intersect list1 list2)
  (display list1) (display " ") (display list2) (newline)
  (cond ((null? list1) list2)
        ((member (car list1) list2) (intersect (cdr list1) list2))
        (else (intersect (cdr list1) (cons (car list1) list2)))))

Here is some simplistic elisp:

(defun is (l1 l2)
  (let ((rtn))
    (mapc
      (lambda (e) 
        (if (member e l1)
          (push e rtn)))
      l2)
    rtn))

This behaves the same as the built-in intersection for these simple tests:

(is '(1 2 5) '(1 4 10 5))  => (5 1)
(intersection '(1 2 5) '(1 4 10 5)) => (5 1)

(is '(1 4 10 5) '(1 2 5)) => (5 1)
(intersection '(1 4 10 5) '(1 2 5)) => (5 1)

You're better off using set operations from srfi-1.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow