views:

409

answers:

4

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))
A: 

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)
killdash10
cannot execute that code. what should i do to run this in drscheme :s thx btw
Sorry, not sure, I am not familiar with drscheme. As I said, this is elisp. Just looking at your code, do you have to use "define" instead of "defun"?
killdash10
yes actually defun doesn't work for me and i don't know how to use defun
The example code is in Emacs Lisp. It has a lot in common with Scheme, and looks very similar but it is a different language.
Zak
A: 

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)))))
Noah Lavine
thanks very much but it seems you did this for getting union of two lists, but i want to take intersection of lists.
Oh, shoot. You're right. This will find the union. The intersection function should be similar, though - just start with '() instead of list2 as your working list. (You might need to add a third argument to the function.)
Noah Lavine
A: 

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))))
tbischel
A: 

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

Mr.Cat