From: jimka
Subject: iteration should be able to do things between iterations
Date: 
Message-ID: <1188823558.616005.22950@r34g2000hsd.googlegroups.com>
A few things i often want to do while iterating over a list is make a
special
case of the first, middle, and last elemens, and perhaps to do things
between iterations
which means if there are no elements or the list is a singleton then
there is no
"between" to consider.   I'm writing this macro primarily for SKILL so
i cannot use off-the-shelf
common lisp macros, but in the mean time i've converted the SKILL
macro to common lisp
to get anyone's feedback who is interested in giving advise.

The code is below.  If you have any comments I'd love to hear them.
Perhaps some
of you have seen similar macros before or implemented them and you
have some
insight into the kinds of pitfalls to watch out for.  Either respond
to me
personally (jimka at rdrop dot com) or to comp.lang.lisp... whichever
you perfer.


The basic easy form is so i can write something like the following

(jterate x '(1 2 3 4 5) (:between (format t "~%|") :before (format t
"<") :after (format t">"))
  (first (format t "the first element is ~A" x)
         (push x stack-of-firsts))
  (trailing (format t "an intermediate element is ~A" x))
  (every (push x stack-of-all))
  (last (format t "the last element is ~A" x)))


;-----------------------------------------------------------------------------

(defmacro foreach (var list &rest body)
  `(dolist (,var ,list)
    ,@body))
(defmacro setof (var list expr)
  `(remove-if-not (lambda (,var) ,expr) ,list))

;; This macro is similar to foreach but allows the caller to easily
;;   make special cases of the first, last, and middle iterations.
;;   :ifempty - expression to evaluate if the list is nil.  This value
;;              is returned from jterate if the list is empty.
;;   :before  - expression to evaluate before the iteration begins
;;              but only if the list is not empty
;;   :after   - expression to evaluate after the iteration normally
;;              but only if the list was not empty.  This value
;;              is returned from jterate if the list is not
;;              empty.
;;   :between - expression to evaluate between iterations.
;;              This expression is never evaluated if the list is
;;              either empty or a singleton list.
;;
;;   Each successive clause after they keyword arguments are sublists
;;   whose first element must be a recognized keyword.
;;   The clauses are effectively spanned on every iteration through
;;   the loop, but only the ones evaluate which are applicable.
;;
;; Applicability designator keywords:
;;   every:  always applicable
;;   first:  only applicable during the first iteration
;;   last:   only applicable during the final iteration.
;;           last is also evaluate even if the list has length 1
;;   middle: applicable on every iteration except the first and last.
;;                thus middle is not evaluated if the list has length
;;                0 or 1.
;;   leading: applicable the 1st, ...N-1st time.  If the list has
length
;;                1 it is applicable during the first iteration.
;;   not-last: applicable the 1st thru n-1st time.  Not applicable at
all if
;;                the list has length 1.
;;   trailing: applicable the 2nd ...Nth time.  Or if the list has
length
;;               1 it is applicable the first iteration.
;;   not-first: applicable 2nd thru Nth time.  Not applicable at all
if
;;                the list has length 1.
;;
;; Notes:
;;    It is permissible to have repeated applicablity designators.
;;    Since the iteration variable is rebound during each iteration
;;       it is permissible to change the value of the iteration
variable
;;       during an iteration.  The effect remains during that
iteration
;;       and will not effect the next iteration.
;;    jterate will only evaluate either :after or :ifempty but not
;;       both.
;;    If the iteration list is empty either the value of :ifemtpy is
;;       returned or nil if :ifempty is not given.
;;    If the iteration list is not empty either the value of :after is
;;       returned or nil if :after is not given.
;;
(defparameter *jterate-mapping*
  '((first     (every first             leading                    not-
last))
    (middle    (every       middle      leading trailing not-first not-
last))
    (last      (every              last         trailing not-first))
    (singleton (every first        last leading trailing))))

(defmacro jterate (var elements (&key ifempty before after between)
		   &rest directives)
  (let ((table (mapcar (lambda (x) (list (car x)))
			  *jterate-mapping*)))
    (foreach directive directives
      (destructuring-bind (key &rest body) directive
	(let ((matching (setof map *jterate-mapping*
			  (memq key (cadr map)))))
	  (if (not matching)
	      (error "no such directive ~A~%" key)
	      (foreach match matching
		       (setf (cdr (assq (car match) table))
			     (append (cdr (assq (car match) table))
				     body)))))))
    (let ((domain    (gensym "domain"))
	  (first     (gensym "first"))
	  (middle    (gensym "middle"))
	  (last      (gensym "last"))
	  (singleton (gensym "singleton")))
      `(let ((,first (lambda (,var)
		       ;;(delcare (ignorable ,var))
		       ,@(cdr (assq 'first table))))
	     (,middle (lambda (,var)
			;;(declare (ignorable ,var))
			,@(cdr (assq 'middle table))))
	     (,last (lambda (,var)
		      ;;(declare (ignorable ,var))
		      ,@(cdr (assq 'last table))))
	     (,singleton (lambda (,var)
			   ;;(declare (ignorable ,var))
			   ,@(cdr (assq 'singleton table))))
	     (,domain ,elements))
	 (cond
	   (,domain
	       (when ',before
		 ,before)
	       (cond
		 ((null (cdr ,domain))
		  (funcall ,singleton (car ,domain)))
		 (t
		  (funcall ,first (car ,domain))
		  (loop for ,var on (cdr ,domain)
			do (progn
			     (when ',between
			       ,between)
			     (if (cdr ,var)
				 (funcall ,middle (car ,var))
				 (funcall ,last (car ,var)))))))
	       (when ',after
		 ,after))
	   (',ifempty
	    ,ifempty)
	   (t nil))))))

(defun test-jterate ()
  (jterate x nil ())
  (jterate x '(1 2 3) (:ifempty 42))
  (jterate x () (:ifempty 42))
  (jterate x '(1 2 3) (:ifempty 42 :after 43))
  (dolist (example '((1 2 3 4 5 6 7)
		      (10 20)
		      (100)
		      ()))

    (jterate x example (:before (format t "example=~A>" example)
				:between (format t "|")
				:after (format t "<~%"))
	     (first (format t "[first ~A]" x))
	     (middle (format t "[middle ~A]" x)
		     (terpri))
	     (not-first (format t "[not-first ~A]" x))
	     (not-last (format t "[not-last ~A]" x))
	     (leading (format t "[leading ~A]" x))
	     (trailing (format t "[trailing ~A]" x))
	     (last (format t "[last ~A]" x)))
  )
  (jterate x '(a b c d e) (:before (format t "(")
				   :between (format t "~%~T")
				   :after (format t ")"))
	   (every (format t "~A" x)))
)

(test-jterate)

From: Karol Skocik
Subject: Re: iteration should be able to do things between iterations
Date: 
Message-ID: <1188825542.476465.46580@r29g2000hsg.googlegroups.com>
On Sep 3, 2:45 pm, jimka <·····@rdrop.com> wrote:
> A few things i often want to do while iterating over a list is make a
> special
> case of the first, middle, and last elemens, and perhaps to do things
> between iterations
> which means if there are no elements or the list is a singleton then
> there is no
> "between" to consider.   I'm writing this macro primarily for SKILL so
> i cannot use off-the-shelf
> common lisp macros, but in the mean time i've converted the SKILL
> macro to common lisp
> to get anyone's feedback who is interested in giving advise.
>
> The code is below.  If you have any comments I'd love to hear them.
> Perhaps some
> of you have seen similar macros before or implemented them and you
> have some
> insight into the kinds of pitfalls to watch out for.  Either respond
> to me
> personally (jimka at rdrop dot com) or to comp.lang.lisp... whichever
> you perfer.
>
> The basic easy form is so i can write something like the following
>
> (jterate x '(1 2 3 4 5) (:between (format t "~%|") :before (format t
> "<") :after (format t">"))
>   (first (format t "the first element is ~A" x)
>          (push x stack-of-firsts))
>   (trailing (format t "an intermediate element is ~A" x))
>   (every (push x stack-of-all))
>   (last (format t "the last element is ~A" x)))
>
> ;-----------------------------------------------------------------------------
>
> (defmacro foreach (var list &rest body)
>   `(dolist (,var ,list)
>     ,@body))
> (defmacro setof (var list expr)
>   `(remove-if-not (lambda (,var) ,expr) ,list))
>
> ;; This macro is similar to foreach but allows the caller to easily
> ;;   make special cases of the first, last, and middle iterations.
> ;;   :ifempty - expression to evaluate if the list is nil.  This value
> ;;              is returned from jterate if the list is empty.
> ;;   :before  - expression to evaluate before the iteration begins
> ;;              but only if the list is not empty
> ;;   :after   - expression to evaluate after the iteration normally
> ;;              but only if the list was not empty.  This value
> ;;              is returned from jterate if the list is not
> ;;              empty.
> ;;   :between - expression to evaluate between iterations.
> ;;              This expression is never evaluated if the list is
> ;;              either empty or a singleton list.
> ;;
> ;;   Each successive clause after they keyword arguments are sublists
> ;;   whose first element must be a recognized keyword.
> ;;   The clauses are effectively spanned on every iteration through
> ;;   the loop, but only the ones evaluate which are applicable.
> ;;
> ;; Applicability designator keywords:
> ;;   every:  always applicable
> ;;   first:  only applicable during the first iteration
> ;;   last:   only applicable during the final iteration.
> ;;           last is also evaluate even if the list has length 1
> ;;   middle: applicable on every iteration except the first and last.
> ;;                thus middle is not evaluated if the list has length
> ;;                0 or 1.
> ;;   leading: applicable the 1st, ...N-1st time.  If the list has
> length
> ;;                1 it is applicable during the first iteration.
> ;;   not-last: applicable the 1st thru n-1st time.  Not applicable at
> all if
> ;;                the list has length 1.
> ;;   trailing: applicable the 2nd ...Nth time.  Or if the list has
> length
> ;;               1 it is applicable the first iteration.
> ;;   not-first: applicable 2nd thru Nth time.  Not applicable at all
> if
> ;;                the list has length 1.
> ;;
> ;; Notes:
> ;;    It is permissible to have repeated applicablity designators.
> ;;    Since the iteration variable is rebound during each iteration
> ;;       it is permissible to change the value of the iteration
> variable
> ;;       during an iteration.  The effect remains during that
> iteration
> ;;       and will not effect the next iteration.
> ;;    jterate will only evaluate either :after or :ifempty but not
> ;;       both.
> ;;    If the iteration list is empty either the value of :ifemtpy is
> ;;       returned or nil if :ifempty is not given.
> ;;    If the iteration list is not empty either the value of :after is
> ;;       returned or nil if :after is not given.
> ;;
> (defparameter *jterate-mapping*
>   '((first     (every first             leading                    not-
> last))
>     (middle    (every       middle      leading trailing not-first not-
> last))
>     (last      (every              last         trailing not-first))
>     (singleton (every first        last leading trailing))))
>
> (defmacro jterate (var elements (&key ifempty before after between)
>                    &rest directives)
>   (let ((table (mapcar (lambda (x) (list (car x)))
>                           *jterate-mapping*)))
>     (foreach directive directives
>       (destructuring-bind (key &rest body) directive
>         (let ((matching (setof map *jterate-mapping*
>                           (memq key (cadr map)))))
>           (if (not matching)
>               (error "no such directive ~A~%" key)
>               (foreach match matching
>                        (setf (cdr (assq (car match) table))
>                              (append (cdr (assq (car match) table))
>                                      body)))))))
>     (let ((domain    (gensym "domain"))
>           (first     (gensym "first"))
>           (middle    (gensym "middle"))
>           (last      (gensym "last"))
>           (singleton (gensym "singleton")))
>       `(let ((,first (lambda (,var)
>                        ;;(delcare (ignorable ,var))
>                        ,@(cdr (assq 'first table))))
>              (,middle (lambda (,var)
>                         ;;(declare (ignorable ,var))
>                         ,@(cdr (assq 'middle table))))
>              (,last (lambda (,var)
>                       ;;(declare (ignorable ,var))
>                       ,@(cdr (assq 'last table))))
>              (,singleton (lambda (,var)
>                            ;;(declare (ignorable ,var))
>                            ,@(cdr (assq 'singleton table))))
>              (,domain ,elements))
>          (cond
>            (,domain
>                (when ',before
>                  ,before)
>                (cond
>                  ((null (cdr ,domain))
>                   (funcall ,singleton (car ,domain)))
>                  (t
>                   (funcall ,first (car ,domain))
>                   (loop for ,var on (cdr ,domain)
>                         do (progn
>                              (when ',between
>                                ,between)
>                              (if (cdr ,var)
>                                  (funcall ,middle (car ,var))
>                                  (funcall ,last (car ,var)))))))
>                (when ',after
>                  ,after))
>            (',ifempty
>             ,ifempty)
>            (t nil))))))
>
> (defun test-jterate ()
>   (jterate x nil ())
>   (jterate x '(1 2 3) (:ifempty 42))
>   (jterate x () (:ifempty 42))
>   (jterate x '(1 2 3) (:ifempty 42 :after 43))
>   (dolist (example '((1 2 3 4 5 6 7)
>                       (10 20)
>                       (100)
>                       ()))
>
>     (jterate x example (:before (format t "example=~A>" example)
>                                 :between (format t "|")
>                                 :after (format t "<~%"))
>              (first (format t "[first ~A]" x))
>              (middle (format t "[middle ~A]" x)
>                      (terpri))
>              (not-first (format t "[not-first ~A]" x))
>              (not-last (format t "[not-last ~A]" x))
>              (leading (format t "[leading ~A]" x))
>              (trailing (format t "[trailing ~A]" x))
>              (last (format t "[last ~A]" x)))
>   )
>   (jterate x '(a b c d e) (:before (format t "(")
>                                    :between (format t "~%~T")
>                                    :after (format t ")"))
>            (every (format t "~A" x)))
> )
>
> (test-jterate)

Nice. You might want to check out iterate library (http://common-
lisp.net/project/iterate/), it solves almost any iteration needs.
From: Javier
Subject: Re: iteration should be able to do things between iterations
Date: 
Message-ID: <1188835147.797429.180640@y42g2000hsy.googlegroups.com>
On 3 sep, 15:19, Karol Skocik <············@gmail.com> wrote:
> On Sep 3, 2:45 pm, jimka <·····@rdrop.com> wrote:
>
>
>
> > A few things i often want to do while iterating over a list is make a
> > special
> > case of the first, middle, and last elemens, and perhaps to do things
> > between iterations
> > which means if there are no elements or the list is a singleton then
> > there is no
> > "between" to consider.   I'm writing this macro primarily for SKILL so
> > i cannot use off-the-shelf
> > common lisp macros, but in the mean time i've converted the SKILL
> > macro to common lisp
> > to get anyone's feedback who is interested in giving advise.
>
> > The code is below.  If you have any comments I'd love to hear them.
> > Perhaps some
> > of you have seen similar macros before or implemented them and you
> > have some
> > insight into the kinds of pitfalls to watch out for.  Either respond
> > to me
> > personally (jimka at rdrop dot com) or to comp.lang.lisp... whichever
> > you perfer.
>
> > The basic easy form is so i can write something like the following
>
> > (jterate x '(1 2 3 4 5) (:between (format t "~%|") :before (format t
> > "<") :after (format t">"))
> >   (first (format t "the first element is ~A" x)
> >          (push x stack-of-firsts))
> >   (trailing (format t "an intermediate element is ~A" x))
> >   (every (push x stack-of-all))
> >   (last (format t "the last element is ~A" x)))
>
> > ;-----------------------------------------------------------------------------
>
> > (defmacro foreach (var list &rest body)
> >   `(dolist (,var ,list)
> >     ,@body))
> > (defmacro setof (var list expr)
> >   `(remove-if-not (lambda (,var) ,expr) ,list))
>
> > ;; This macro is similar to foreach but allows the caller to easily
> > ;;   make special cases of the first, last, and middle iterations.
> > ;;   :ifempty - expression to evaluate if the list is nil.  This value
> > ;;              is returned from jterate if the list is empty.
> > ;;   :before  - expression to evaluate before the iteration begins
> > ;;              but only if the list is not empty
> > ;;   :after   - expression to evaluate after the iteration normally
> > ;;              but only if the list was not empty.  This value
> > ;;              is returned from jterate if the list is not
> > ;;              empty.
> > ;;   :between - expression to evaluate between iterations.
> > ;;              This expression is never evaluated if the list is
> > ;;              either empty or a singleton list.
> > ;;
> > ;;   Each successive clause after they keyword arguments are sublists
> > ;;   whose first element must be a recognized keyword.
> > ;;   The clauses are effectively spanned on every iteration through
> > ;;   the loop, but only the ones evaluate which are applicable.
> > ;;
> > ;; Applicability designator keywords:
> > ;;   every:  always applicable
> > ;;   first:  only applicable during the first iteration
> > ;;   last:   only applicable during the final iteration.
> > ;;           last is also evaluate even if the list has length 1
> > ;;   middle: applicable on every iteration except the first and last.
> > ;;                thus middle is not evaluated if the list has length
> > ;;                0 or 1.
> > ;;   leading: applicable the 1st, ...N-1st time.  If the list has
> > length
> > ;;                1 it is applicable during the first iteration.
> > ;;   not-last: applicable the 1st thru n-1st time.  Not applicable at
> > all if
> > ;;                the list has length 1.
> > ;;   trailing: applicable the 2nd ...Nth time.  Or if the list has
> > length
> > ;;               1 it is applicable the first iteration.
> > ;;   not-first: applicable 2nd thru Nth time.  Not applicable at all
> > if
> > ;;                the list has length 1.
> > ;;
> > ;; Notes:
> > ;;    It is permissible to have repeated applicablity designators.
> > ;;    Since the iteration variable is rebound during each iteration
> > ;;       it is permissible to change the value of the iteration
> > variable
> > ;;       during an iteration.  The effect remains during that
> > iteration
> > ;;       and will not effect the next iteration.
> > ;;    jterate will only evaluate either :after or :ifempty but not
> > ;;       both.
> > ;;    If the iteration list is empty either the value of :ifemtpy is
> > ;;       returned or nil if :ifempty is not given.
> > ;;    If the iteration list is not empty either the value of :after is
> > ;;       returned or nil if :after is not given.
> > ;;
> > (defparameter *jterate-mapping*
> >   '((first     (every first             leading                    not-
> > last))
> >     (middle    (every       middle      leading trailing not-first not-
> > last))
> >     (last      (every              last         trailing not-first))
> >     (singleton (every first        last leading trailing))))
>
> > (defmacro jterate (var elements (&key ifempty before after between)
> >                    &rest directives)
> >   (let ((table (mapcar (lambda (x) (list (car x)))
> >                           *jterate-mapping*)))
> >     (foreach directive directives
> >       (destructuring-bind (key &rest body) directive
> >         (let ((matching (setof map *jterate-mapping*
> >                           (memq key (cadr map)))))
> >           (if (not matching)
> >               (error "no such directive ~A~%" key)
> >               (foreach match matching
> >                        (setf (cdr (assq (car match) table))
> >                              (append (cdr (assq (car match) table))
> >                                      body)))))))
> >     (let ((domain    (gensym "domain"))
> >           (first     (gensym "first"))
> >           (middle    (gensym "middle"))
> >           (last      (gensym "last"))
> >           (singleton (gensym "singleton")))
> >       `(let ((,first (lambda (,var)
> >                        ;;(delcare (ignorable ,var))
> >                        ,@(cdr (assq 'first table))))
> >              (,middle (lambda (,var)
> >                         ;;(declare (ignorable ,var))
> >                         ,@(cdr (assq 'middle table))))
> >              (,last (lambda (,var)
> >                       ;;(declare (ignorable ,var))
> >                       ,@(cdr (assq 'last table))))
> >              (,singleton (lambda (,var)
> >                            ;;(declare (ignorable ,var))
> >                            ,@(cdr (assq 'singleton table))))
> >              (,domain ,elements))
> >          (cond
> >            (,domain
> >                (when ',before
> >                  ,before)
> >                (cond
> >                  ((null (cdr ,domain))
> >                   (funcall ,singleton (car ,domain)))
> >                  (t
> >                   (funcall ,first (car ,domain))
> >                   (loop for ,var on (cdr ,domain)
> >                         do (progn
> >                              (when ',between
> >                                ,between)
> >                              (if (cdr ,var)
> >                                  (funcall ,middle (car ,var))
> >                                  (funcall ,last (car ,var)))))))
> >                (when ',after
> >                  ,after))
> >            (',ifempty
> >             ,ifempty)
> >            (t nil))))))
>
> > (defun test-jterate ()
> >   (jterate x nil ())
> >   (jterate x '(1 2 3) (:ifempty 42))
> >   (jterate x () (:ifempty 42))
> >   (jterate x '(1 2 3) (:ifempty 42 :after 43))
> >   (dolist (example '((1 2 3 4 5 6 7)
> >                       (10 20)
> >                       (100)
> >                       ()))
>
> >     (jterate x example (:before (format t "example=~A>" example)
> >                                 :between (format t "|")
> >                                 :after (format t "<~%"))
> >              (first (format t "[first ~A]" x))
> >              (middle (format t "[middle ~A]" x)
> >                      (terpri))
> >              (not-first (format t "[not-first ~A]" x))
> >              (not-last (format t "[not-last ~A]" x))
> >              (leading (format t "[leading ~A]" x))
> >              (trailing (format t "[trailing ~A]" x))
> >              (last (format t "[last ~A]" x)))
> >   )
> >   (jterate x '(a b c d e) (:before (format t "(")
> >                                    :between (format t "~%~T")
> >                                    :after (format t ")"))
> >            (every (format t "~A" x)))
> > )
>
> > (test-jterate)
>
> Nice. You might want to check out iterate library (http://common-
> lisp.net/project/iterate/), it solves almost any iteration needs.

I'm trying to use that package, which works great except that it
raises an error when trying to use (use-package 'iterator):

USE-PACKAGE #<PACKAGE "ITERATE"> causes name-conflicts in
#<PACKAGE "COMMON-LISP-USER"> between the following symbols:
  ITERATE:ITERATE, ITERATE

It allows me to continue loading it, and it works, but it is not
convenient that every time I open a file using the package ITERATOR,
it enters into the debugger. How can I avoid this error?
From: Karol Skocik
Subject: Re: iteration should be able to do things between iterations
Date: 
Message-ID: <1188849057.387444.315170@g4g2000hsf.googlegroups.com>
On Sep 3, 5:59 pm, Javier <·······@gmail.com> wrote:
> On 3 sep, 15:19, Karol Skocik <············@gmail.com> wrote:
>
>
>
> > On Sep 3, 2:45 pm, jimka <·····@rdrop.com> wrote:
>
> > > A few things i often want to do while iterating over a list is make a
> > > special
> > > case of the first, middle, and last elemens, and perhaps to do things
> > > between iterations
> > > which means if there are no elements or the list is a singleton then
> > > there is no
> > > "between" to consider.   I'm writing this macro primarily for SKILL so
> > > i cannot use off-the-shelf
> > > common lisp macros, but in the mean time i've converted the SKILL
> > > macro to common lisp
> > > to get anyone's feedback who is interested in giving advise.
>
> > > The code is below.  If you have any comments I'd love to hear them.
> > > Perhaps some
> > > of you have seen similar macros before or implemented them and you
> > > have some
> > > insight into the kinds of pitfalls to watch out for.  Either respond
> > > to me
> > > personally (jimka at rdrop dot com) or to comp.lang.lisp... whichever
> > > you perfer.
>
> > > The basic easy form is so i can write something like the following
>
> > > (jterate x '(1 2 3 4 5) (:between (format t "~%|") :before (format t
> > > "<") :after (format t">"))
> > >   (first (format t "the first element is ~A" x)
> > >          (push x stack-of-firsts))
> > >   (trailing (format t "an intermediate element is ~A" x))
> > >   (every (push x stack-of-all))
> > >   (last (format t "the last element is ~A" x)))
>
> > > ;-----------------------------------------------------------------------------
>
> > > (defmacro foreach (var list &rest body)
> > >   `(dolist (,var ,list)
> > >     ,@body))
> > > (defmacro setof (var list expr)
> > >   `(remove-if-not (lambda (,var) ,expr) ,list))
>
> > > ;; This macro is similar to foreach but allows the caller to easily
> > > ;;   make special cases of the first, last, and middle iterations.
> > > ;;   :ifempty - expression to evaluate if the list is nil.  This value
> > > ;;              is returned from jterate if the list is empty.
> > > ;;   :before  - expression to evaluate before the iteration begins
> > > ;;              but only if the list is not empty
> > > ;;   :after   - expression to evaluate after the iteration normally
> > > ;;              but only if the list was not empty.  This value
> > > ;;              is returned from jterate if the list is not
> > > ;;              empty.
> > > ;;   :between - expression to evaluate between iterations.
> > > ;;              This expression is never evaluated if the list is
> > > ;;              either empty or a singleton list.
> > > ;;
> > > ;;   Each successive clause after they keyword arguments are sublists
> > > ;;   whose first element must be a recognized keyword.
> > > ;;   The clauses are effectively spanned on every iteration through
> > > ;;   the loop, but only the ones evaluate which are applicable.
> > > ;;
> > > ;; Applicability designator keywords:
> > > ;;   every:  always applicable
> > > ;;   first:  only applicable during the first iteration
> > > ;;   last:   only applicable during the final iteration.
> > > ;;           last is also evaluate even if the list has length 1
> > > ;;   middle: applicable on every iteration except the first and last.
> > > ;;                thus middle is not evaluated if the list has length
> > > ;;                0 or 1.
> > > ;;   leading: applicable the 1st, ...N-1st time.  If the list has
> > > length
> > > ;;                1 it is applicable during the first iteration.
> > > ;;   not-last: applicable the 1st thru n-1st time.  Not applicable at
> > > all if
> > > ;;                the list has length 1.
> > > ;;   trailing: applicable the 2nd ...Nth time.  Or if the list has
> > > length
> > > ;;               1 it is applicable the first iteration.
> > > ;;   not-first: applicable 2nd thru Nth time.  Not applicable at all
> > > if
> > > ;;                the list has length 1.
> > > ;;
> > > ;; Notes:
> > > ;;    It is permissible to have repeated applicablity designators.
> > > ;;    Since the iteration variable is rebound during each iteration
> > > ;;       it is permissible to change the value of the iteration
> > > variable
> > > ;;       during an iteration.  The effect remains during that
> > > iteration
> > > ;;       and will not effect the next iteration.
> > > ;;    jterate will only evaluate either :after or :ifempty but not
> > > ;;       both.
> > > ;;    If the iteration list is empty either the value of :ifemtpy is
> > > ;;       returned or nil if :ifempty is not given.
> > > ;;    If the iteration list is not empty either the value of :after is
> > > ;;       returned or nil if :after is not given.
> > > ;;
> > > (defparameter *jterate-mapping*
> > >   '((first     (every first             leading                    not-
> > > last))
> > >     (middle    (every       middle      leading trailing not-first not-
> > > last))
> > >     (last      (every              last         trailing not-first))
> > >     (singleton (every first        last leading trailing))))
>
> > > (defmacro jterate (var elements (&key ifempty before after between)
> > >                    &rest directives)
> > >   (let ((table (mapcar (lambda (x) (list (car x)))
> > >                           *jterate-mapping*)))
> > >     (foreach directive directives
> > >       (destructuring-bind (key &rest body) directive
> > >         (let ((matching (setof map *jterate-mapping*
> > >                           (memq key (cadr map)))))
> > >           (if (not matching)
> > >               (error "no such directive ~A~%" key)
> > >               (foreach match matching
> > >                        (setf (cdr (assq (car match) table))
> > >                              (append (cdr (assq (car match) table))
> > >                                      body)))))))
> > >     (let ((domain    (gensym "domain"))
> > >           (first     (gensym "first"))
> > >           (middle    (gensym "middle"))
> > >           (last      (gensym "last"))
> > >           (singleton (gensym "singleton")))
> > >       `(let ((,first (lambda (,var)
> > >                        ;;(delcare (ignorable ,var))
> > >                        ,@(cdr (assq 'first table))))
> > >              (,middle (lambda (,var)
> > >                         ;;(declare (ignorable ,var))
> > >                         ,@(cdr (assq 'middle table))))
> > >              (,last (lambda (,var)
> > >                       ;;(declare (ignorable ,var))
> > >                       ,@(cdr (assq 'last table))))
> > >              (,singleton (lambda (,var)
> > >                            ;;(declare (ignorable ,var))
> > >                            ,@(cdr (assq 'singleton table))))
> > >              (,domain ,elements))
> > >          (cond
> > >            (,domain
> > >                (when ',before
> > >                  ,before)
> > >                (cond
> > >                  ((null (cdr ,domain))
> > >                   (funcall ,singleton (car ,domain)))
> > >                  (t
> > >                   (funcall ,first (car ,domain))
> > >                   (loop for ,var on (cdr ,domain)
> > >                         do (progn
> > >                              (when ',between
> > >                                ,between)
> > >                              (if (cdr ,var)
> > >                                  (funcall ,middle (car ,var))
> > >                                  (funcall ,last (car ,var)))))))
> > >                (when ',after
> > >                  ,after))
> > >            (',ifempty
> > >             ,ifempty)
> > >            (t nil))))))
>
> > > (defun test-jterate ()
> > >   (jterate x nil ())
> > >   (jterate x '(1 2 3) (:ifempty 42))
> > >   (jterate x () (:ifempty 42))
> > >   (jterate x '(1 2 3) (:ifempty 42 :after 43))
> > >   (dolist (example '((1 2 3 4 5 6 7)
> > >                       (10 20)
> > >                       (100)
> > >                       ()))
>
> > >     (jterate x example (:before (format t "example=~A>" example)
> > >                                 :between (format t "|")
> > >                                 :after (format t "<~%"))
> > >              (first (format t "[first ~A]" x))
> > >              (middle (format t "[middle ~A]" x)
> > >                      (terpri))
> > >              (not-first (format t "[not-first ~A]" x))
> > >              (not-last (format t "[not-last ~A]" x))
> > >              (leading (format t "[leading ~A]" x))
> > >              (trailing (format t "[trailing ~A]" x))
> > >              (last (format t "[last ~A]" x)))
> > >   )
> > >   (jterate x '(a b c d e) (:before (format t "(")
> > >                                    :between (format t "~%~T")
> > >                                    :after (format t ")"))
> > >            (every (format t "~A" x)))
> > > )
>
> > > (test-jterate)
>
> > Nice. You might want to check out iterate library (http://common-
> > lisp.net/project/iterate/), it solves almost any iteration needs.
>
> I'm trying to use that package, which works great except that it
> raises an error when trying to use (use-package 'iterator):
>
> USE-PACKAGE #<PACKAGE "ITERATE"> causes name-conflicts in
> #<PACKAGE "COMMON-LISP-USER"> between the following symbols:
>   ITERATE:ITERATE, ITERATE
>
> It allows me to continue loading it, and it works, but it is not
> convenient that every time I open a file using the package ITERATOR,
> it enters into the debugger. How can I avoid this error?

The problem here is probably, that since you have installed iterate
like
(asdf-install:install 'iterate) iterate symbol is now interned in cl-
user package giving you conflict.

use-package does not scale well when you have more packages in your
app.
This is example of something what I use:

(in-package #:cl-user)

;; I want these libs to be loaded:
(require :metabang-bind)
(require :iterate)
(require :cl-utilities)
(require :cl-store)
(require :ltk)
(require :patg)


(defpackage #:tactix
  (:use :patg :asdf :cl :cl-utilities :cl-
store :iterate :bind :ltk :sb-thread :sb-bsd-sockets :sb-alien :sb-
sys)  ;; I want these to be in the same namespace
  (:shadow move event) ;; except these
  (:shadow cl-utilities:partition-if cl-utilities:partition-if-not) ;;
except these as well
  (:shadowing-import-from iterate collect collecting) ;; collect and
collecting are now symbols from iterate package
  (:shadowing-import-from bind bind) ;; the same
  (:shadowing-import-from patg partition)) ;; the same

... some defsystem here maybe, when you have more files and
dependencies between them..
From: Rob Warnock
Subject: Re: iteration should be able to do things between iterations
Date: 
Message-ID: <48idnWcj8cvFIUHbnZ2dnUVZ_rignZ2d@speakeasy.net>
Javier  <·······@gmail.com> wrote:
+---------------
| > Nice. You might want to check out iterate library (http://common-
| > lisp.net/project/iterate/), it solves almost any iteration needs.
| 
| I'm trying to use that package, which works great except that it
| raises an error when trying to use (use-package 'iterator):
| 
| USE-PACKAGE #<PACKAGE "ITERATE"> causes name-conflicts in
| #<PACKAGE "COMMON-LISP-USER"> between the following symbols:
|   ITERATE:ITERATE, ITERATE
| 
| It allows me to continue loading it, and it works, but it is not
| convenient that every time I open a file using the package ITERATOR,
| it enters into the debugger. How can I avoid this error?
+---------------

If you're using CMUCL [or maybe SBCL?], the problem is the current
package COMMON-LISP-USER already USEs the CMUCL EXTENSIONS package,
and there's already an ITERATE macro there:

  cmu> (describe 'ITERATE)

  ITERATE is an external symbol in the EXTENSIONS package.
  Macro-function: #<Byte function (:MACRO ITERATE) {28FA89D1}>
  Macro documentation:
    Iterate Name ({(Var Initial-Value)}*) Declaration* Form*
    This is syntactic sugar for Labels.  It creates a local function Name with
    the specified Vars as its arguments and the Declarations and Forms as its
    body.  This function is then called with the Initial-Values, and the result
    of the call is return from the macro.
  On Wednesday, 11/16/05 05:13:44 pm PST it was compiled from:
  target:code/extensions.lisp
    Created: Sunday, 10/5/03 04:41:22 am PDT
    Comment: $Header: /project/cmucl/cvsroot/src/code/extensions.lisp,v 1.28 2003/
  10/05 11:41:22 gerd Exp $
  cmu> 

So in order to USE the ITERATOR package [and as a parellel reply
noted, that might not be te best thing to do], you will need to do
a shadowing import of ITERATE:ITERATE into COMMON-LISP-USER *before*
doing a (USE-PACKAGE "ITERATOR").


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: jimka
Subject: Re: iteration should be able to do things between iterations
Date: 
Message-ID: <1188913830.386848.260680@57g2000hsv.googlegroups.com>
sorry, i think the discussion and ventured a bit.  I was asking
whether anyone had any
comments (positive or negative) about my suggested jterate macro.  I
was hoping not to
venture into a discussion of the iterate facility which might be very
interesting but
more appropriate for a different thread.

kind regards
-jim
From: Ken Tilton
Subject: Re: iteration should be able to do things between iterations
Date: 
Message-ID: <bfeDi.27$aS.6@newsfe12.lga>
jimka wrote:
> sorry, i think the discussion and ventured a bit. 

welcome to usenet. wait till the thread gets back to whether french 
schoolchildren should be allowed to wear headscarves before you complain.

hth,kenny

-- 
http://www.theoryyalgebra.com/

"We are what we pretend to be." -Kurt Vonnegut
From: Ed Symanzik
Subject: Re: iteration should be able to do things between iterations
Date: 
Message-ID: <fbmuj2$dc4$1@news.msu.edu>
Ken Tilton wrote:
> 
> 
> jimka wrote:
>> sorry, i think the discussion and ventured a bit. 
> 
> welcome to usenet. wait till the thread gets back to whether french
> schoolchildren should be allowed to wear headscarves before you complain.
> 
> hth,kenny
> 

I hear Hitler was fond of headscarves.