
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