here is the code and its working fine on scheme lisp
(define (rdup ls)
(let loop ((ls ls) (current #f))
(cond ((null? ls) ())
((null? (cdr ls)) (if (eq? (car ls) current) () ls))
((eq? (car ls) (cadr ls)) (loop (cdr ls) (car ls)))
((eq? (car ls) current) (loop (cdr ls) current))
(else (cons (car ls) (loop (cdr ls) (car ls)))) )))
and here is what i tried
(rdup '(a b a a a c c))
and got (a b)
I want to know how each line of the code works
I've added line numbers and fixed your indentation to make it easier to explain:
01 (define (rdup ls)
02 (let loop ((ls ls)
03 (current #f))
04 (cond
05 ((null? ls) '())
06 ((null? (cdr ls))
07 (if (eq? (car ls) current) '() ls))
08 ((eq? (car ls) (cadr ls))
09 (loop (cdr ls) (car ls)))
10 ((eq? (car ls) current)
11 (loop (cdr ls) current))
12 (else (cons (car ls)
13 (loop (cdr ls) (car ls)))))))
Line 02: You are using a special form of the let syntax to create a named procedure that you can then call from within the let. You are defining (confusingly) a variable inside the loop ls
with the exact same name as a variable outside of the loop, giving the internal variable the initial value of the external one. You are also defining a second parameter, current
that you are giving the initial value of #f
.
Line 04 starts a cond
.
Line 05 (I corrected it so it would work by quoting the empty list) returns an empty list if ls
is null. This stops the procedure and unwinds the stack.
Line 06 checks if the cdr
is null, indicating that you are operating on the last element of the list. If that is true, you go to line 07 and either return an empty list if the car
of ls
is equal to current
, or you return ls
. This also ends the procedure and unwinds the stack.
Lines 08-09 look for duplicates in a row and if so it calls the loop procedure using the cdr
as the new list and the car
as the current
.
Lines 10-11 check if the car
is equal to current
and if so it calls the loop procedure with the cdr
(again iterating down the list) and current
.
If none of those conditions are met, lines 12-13 will create a new list by cons
-ing the car
of ls
with the result of calling the let
-created loop
procedure on the cdr
of ls
and the car
of ls
.
If the procedure worked as intended, it should have returned '(a b c)
.
Here's one that works as I think your program is intended to work:
(define rdup
(lambda (l)
(reverse (let loop ((lst l)
(c '()))
(cond
((null? lst) c)
(else
(if (member (car lst) c)
(loop (cdr lst) c)
(loop (cdr lst) (cons (car lst) c)))))))))