help trying to write a function

Quote:

> I am trying to write a function, unique, which takes a list and returns

> unique elements of that list for example

> (unique '(a b c d b a)) => (a b c d)

> this is what I have:

> (define (unique l)

> (cond

> ((null? l) '())

> (else((cons (car l) (unique(remove-if equal? (car l) (cdrl))))))))

> I know the concept is correct (isn't it?) however remove-if has two

> parameters, the predicate and the list.

No. In your code remove-if is given three arguments: 1) the equality

predicate 2) the element to be removed and 3) the list from which the

element is to be removed.

Quote:

> My question: Is "equal?" the

> predicate or is "equal? (car l)" the predicate? If just "equal?" is the

> predicate how do I proceed?

The concept is right, although it is not the only one possible, as you have

correctly grasped. The way you have written function unique, equal? is the

predicate and remove-if must be defined as a function of three arguments, 1)

the equality predicate, 2) the element to be removed and 3) the list it is

to be removed from. Sticking to your version of unique, remove-if must have

three arguments, say eq-predicate, element-to-be-removed and lst. It must

have three cond alternatives:

1) you cannot remove anything from the empty list

2) if the element-to-be-removed is eq-predicate with the first element of

lst then ...

3) if the element-to-be-removed is not eq-predicate with the first element

then ...

Another solution can be:

(define (unique l)

(cond

((null? l) '())

(else((cons (car l) (unique (remove-if (lambda (x) (equal? x (car l)))

(cdrl)))))))

Now (lambda (x) (equal? x (car l))) is a predicate taking one argument and

remove-if takes two arguments, namely the predicate (applied to one element)

and a list from which all elements satisfying the predicate must be removed.

This version of remove-if has three cond alternatives too.

1) you cannot remove anything from the empty list

2) if the first element of lst satisfies the predicate then ...

3) if the first element of lst does not satisfy the predicate then ...

You also may consider:

(define (unique l)

(cond

((null? l) '())

(else((cons (car l) (unique (remove-if (relation->predicate equal? (car

l)) (cdrl)))))))

where (relation->predicate eq-predicate element) must produce (lambda (x)

(eq-predicate element x)). I strongly suggest to try both of the first two

solutions. If you feel comfortable about these two you can also try the

third one. If that goes well, you also may consider to write unique such as

to accept two arguments: a (binary) equality relation and the list to be

processed.

Hope this helps, Jos.

PS. I know that lots of people call an equality relation a predicate. For

myself I reserve the word *predicate* for functions of one argument. The

function returns true if the argument has the predicate, else it returns

false. Equality is a(n equivalence) relation rather than a predicate. In

this view a relation is a predicate of doublets of objects. In this view

zero? and (lambda (x) (> x 3)) and (lambda (x) (equal? x 5)) are predicates

but equal? and > themselves are relations. Compare: (lambda (x y) (equal? x

y)) with (lambda (doublet) (equal? (car doublet) (cadr (doublet)))). The

former I call a relation, the latter a predicate. In short: a binary

relation x,y--> true/false in a set A can be viewed as a predicate

doublet --> false/true in the set A*A.

Jos