1

This is the Common Lisp code:

(defun take (L)
  (if (null L) nil
     (cons (car L) (skip (cdr L)))))

(defun skip (L)
  (if (null L) nil
     (cons (car L) (take (cdr L)))))

The idea here is that, "take" will give all the odd sequence elements in the input list and "skip" will give all the even sequence elements in the input list. However, in both cases the entire list is returned.

What is the error in this code? Is this something to do with how CL handles lists, because the similar code in SML gives the desired output.

fun take(lst) = 
     if lst = nil then nil 
     else hd(lst)::skip(tl(lst))
and
    skip(lst) = 
     if lst = nil then nil 
     else hd(lst)::take(tl(lst));
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • Your `take` doesn't return the odd indexed elements, but the even ones. Indexing starts at `0`, and `take` would return elements `0`, `2`, `4`, etc., if it includes `(car L) == (nth 0 L)`. – Joshua Taylor Nov 24 '13 at 04:05

3 Answers3

4

To expound on what Sylwester has said, your skip is wrong in both Lisp and SML. It should be

(defun take (L)         ; even-indexed elements of a list L
  (if (not (null L))
     (cons (car L) (skip (cdr L)))))

(defun skip (L)         ; odd-indexed elements of a list L
  (if (not (null L))
     (take (cdr L))))

and

fun take(lst) = 
     if lst = nil then nil 
     else hd(lst)::skip(tl(lst))
and
    skip(lst) = 
     if lst = nil then nil 
     else take(tl(lst));
Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • 1
    Btw, consider using (unless ...) instead of a one-branch (if (not ...) ...) – PuercoPop Nov 24 '13 at 04:42
  • @PuercoPop Thanks, but I dislike `unless` very very much, it is very confusing, to me: it is used in different modality in English, where it is "don't do this, unless..." while in CL it is "unless ..., do this". Besides, it's not *my* code, it the OP's. I only *corrected* it. :) – Will Ness Nov 24 '13 at 06:18
3

The take and skip are identical so that is no mystery. skip should just tail call instead of cons-ing. It's the consing that makes the return here.

Sylwester
  • 47,942
  • 4
  • 47
  • 79
2

It's worth pointing out that indexing in Common Lisp (like many other programming languages) starts with 0, so the even-indexed elements of a list are the first, the third, the fifth, and so on, since those have indices 0, 2, 4, etc. It's also worth noting that in Common Lisp, you can take the rest of the empty list and get back the empty list. (You can't do this in every Lisp, though. E.g., in Scheme it's an error to call cdr on something that's not a pair.) This means that you can implement even-elements and odd-elements rather easily. even-elementsjust returns a list of the first element, and the odd elements of the rest of the list. odd-elements returns the even-elements of the rest of the list:

(defun even-elements (list)
  (if (endp list) list
      (list* (first list) (odd-elements (rest list)))))

(defun odd-elements (list)
  (even-elements (rest list)))

These behave in the expected fashion:

CL-USER> (even-elements '(0 1 2 3 4 5))
(0 2 4)
CL-USER> (odd-elements '(0 1 2 3 4 5))
(1 3 5)

Of course, if you note that the call to (odd-elements x) is just a call to (even-elements (rest x)), we could have implemented even-elements as follows, and had the same result:

(defun even-elements (list)
  (if (endp list) list
      (list* (first list) (even-elements (rest (rest list))))))
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353