Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Critique my Lisp, please [closed]

I have created a nice little routine:

(defun unzip (seq)
  "Takes an even-length list and breaks it apart by evens/odd index"
  (let ((oddresult '())
    (evenresult '()))
    (loop for n from 0 to (- (length seq) 1) do
      (if (oddp n)
          (push (nth n seq) oddresult)
        (push (nth n seq) evenresult)))
    (list (reverse oddresult) (reverse evenresult))))

And to use it:

CL-USER> (unzip '(1 2 3 4 5 6))
((2 4 6) (1 3 5))

However, I am keenly aware of my ability to writebotch C++ in any language, and would like some analysis of my unzip for good Common Lisp style.

like image 806
Paul Nathan Avatar asked Oct 09 '10 06:10

Paul Nathan


1 Answers

First note that '() and () are equivalent, since empty list is self evaluating and equal to NIL, and in any case you don't need those in LET because NIL is implied by `(let (variable) ...) syntax, which is a reason why you need a parenthesis around each binding when giving the a starting value.

Not that using LET is necessary for this case. Using LOOP features more extensively this function can be written as:

(defun unzip (seq)
  "Takes an even-length list and breaks it apart by evens/odd index"
  (loop for n from 0
        for element in seq
        if (oddp n)
          collect element into oddresult
        else
          collect element into evenresult
        finally (return (list oddresult evenresult))))

Personally I prefer iterate for most iteration, using which it can be written as:

(defun unzip (seq)
  "Takes an even-length list and breaks it apart by evens/odd index"
  (iter (for element in seq)
        (for n from 0)
        (if (oddp n)
            (collect element into oddresult)
            (collect element into evenresult))
        (finally (return (list oddresult evenresult)))))

or even:

(defun unzip (seq)
  "Takes an even-length list and breaks it apart by evens/odd index"
  (iter (generate element in seq)
        (collect (next element) into evenresult)
        (collect (next element) into oddresult)
        (finally (return (list oddresult evenresult)))))

EDIT: Additional notes: The name unzip conventionally denotes a slightly different function. The argument name should really be list, since seq would suggest the the function also takes vectors. While it is possible to have functions operating on generalized sequences, it is usually not recommended, since lists and vectors have different performance characteristics. In particular, random access through NTH is linear time for lists, which means you should almost never use it. Even if the time cost is insignificant it usually indicates you should be using a different datastructure.

like image 112
Ramarren Avatar answered Oct 31 '22 05:10

Ramarren