1

I wrote a simple intersection function on two lists:

(define (intersection l1 l2)
  (if (null? l1) '()
      (if (member (car l1) l2)
          (cons (car l1) (intersection (cdr l1) l2))
          (intersection (cdr l1) l2))))

But I can't get replace this code so that (intersection (cdr l1) l2) only appears once as in:

(define (intersection l1 l2)
  (if (null? l1) '()
      (let (appel '(intersection (cdr l1) l2))
        (if (member (car l1) l2)
            (cons (car l1) appel)
            appel))))

I try also to replace appel with (eval appel) but it didn' work.

2
  • 3
    This is just due to typos: quoted list bound to appel and missing parentheses in the let form. Commented Jun 9 at 0:24
  • to be clear: the list bound to appel in the let form does not need to be quoted, and an extra pair of parentheses need to be put around that binding. Commented Jun 17 at 17:23

3 Answers 3

3

I try also to replace appel with (eval appel) but it didn' work.

The expression (eval '(intersection (cdr l1) l2)) will eventually evaluate l1 and l2, which are free variables in the expression. You didn't show which error you had but you probably encountered something like this:

reference to undefined identifier: l1

Function calls do not capture the current lexical environment; eval is not special here, it doesn't have access to the bindings that are present in the source code when it is being executed.

Sign up to request clarification or add additional context in comments.

Comments

1

It should be:

(define (intersection l1 l2)
  (if (null? l1) 
      '()
      (let ((res (intersection (cdr l1) l2)))
        (if (member (car l1) l2)
            (cons (car l1) res)
            res))))

Instead of the ifs, it is preferable to use cond:

(define (intersection l1 l2)
  (cond ((null? l1) '())
        (else (let ((res (intersection (cdr l1) l2)))
                (cond ((member (car l1) l2) (cons (car l1) res))
                      (else res))))))

But better is to do tail call recursion (max recursion depth can't do then any harm):

(define (intersection l1 l2 (acc '()))
  (cond ((null? l1) (reverse acc))
        ((member (car l1) l2) (intersection (rest l1) l2 (cons (car l1) acc)))
        (else (intersection (rest l1) l2 acc))))

Or using ifs:

(define (intersection l1 l2 (acc '()))
  (if (null? l1)
      (reverse acc)
      (intersection (cdr l1) l2 (if (member (car l1) l2)
                                    (cons (car l1) acc)
                                    acc))))

3 Comments

Can you explain why, in this alternative case, is it preferable to use cond ? or is this a general advice using Scheme ?
cond is a different way to express conditions - syntactic sugar - especially when ifs are chained. cond is beautiful, because it puts condition and the consequence next to each other like in a table. I personally like cond more than if. Also, if you chain ifs, then the indentation of the code has to wander to the right side. But with cond everything is nicely aligned at one indentation level. And one has a nice overview over the conditions (first after the indentation) an aligned to one "column" while with if you have condition and consequences aligned to the sa
As a counter point, in cases where there's only two branches and both are single expressions, I think if is preferable and more readable. Leave cond for multi-way branching and branches with multiple sequential expressions (to avoid wrapping them in explicit begins). And for a single branch, when and unless. I've seen people combine cond and let in a single macro that lets you either have a test case or define a variable for all following tests that might be useful here, though.
-2

The result of the recursive call just needs to be bound to a variable, not quoted.
let evaluates the right hand side automatically, so there's no need write a leading quote and you certainly don’t need eval.

(define (intersection l1 l2)
  (if (null? l1)
      '()
      (let ((tail (intersection (cdr l1) l2))) 
            (cons (car l1) tail)               
            tail))))

3 Comments

Thx @Rian with your code, I just notice I forgot an opening parenthesis!!!
You left out an important part of the original.
(cons (car l1) tail) has no effect, and overall the parentheses aren't balanced.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.