(defmacro for (x in g &rest act) "'x' can be one atom or a list of varaibles. 'g' is a function that returns a lambda body That lambda returns 1 value or multiple values using '(values x y...)'. This macro terminates then the first item of 'x' is nil" (declare (ignore in)) (let ((name (gensym "NAME")) (next (gensym "LAMBDA")) (items (if (listp x) x (list x))) (one (if (listp x) (car x) x))) `(block ,name (let ((,next ,g)) (loop (multiple-value-bind ,items (funcall ,next) (unless ,one (return-from ,name)) ,@act)))))) (defun odds (max) (let ((i 0)) (lambda () (incf i) (if (evenp i) (incf i)) (if (<= i max) i)))) (defun _for1 () (for item in (odds 10) (print item))) (defun oddeven (lst) (let ((copy (copy-list lst))) (lambda () (when lst (let ((odd (pop copy)) (even (pop copy)))3 (and odd even (values odd even))))))) (defun _for2 () (for (odd even) in (oddeven '(tim m toni f lucie f)) (print `(odd ,odd even ,even)) )) ; polymorphic interators. pretty tricky... (defmethod contents ((l1 list)) (let ((l2 l1) (n -1)) (lambda () (if l2 (let ((tmp (pop l2))) (incf n) (values n tmp)))))) (defmethod contents ((h hash-table)) (let (keys) (maphash (lambda (key v) (declare (ignore v)) (push key keys)) h) (lambda () (if keys (let ((key (pop keys))) (values key (gethash key h))))))) (defun _for3a () (for (where what) in (contents '(a b c d e)) (print `(where ,where what ,what)))) (defun _for3b () (let ((h (make-hash-table))) (dotimes (i 100) (setf (gethash (random 100) h) (random 100))) (for (where what) in (contents h) (print `(where ,where what ,what)))) ) (defun _for4 () (macroexpand '(for (odd even) in (oddeven '(tim m toni f lucie f)) (print `(odd ,odd even ,even)))))