From: Kenneth Tilton
Subject: It's A Big Language Survey
Date: 
Message-ID: <49f1b6ea$0$27759$607ed4bc@cv.net>
Lisp G*ds Only, for reasons obvious:

What is/are the big chunks of CL you have never used? Series does not count.

Motivation: my standard retort to Lisp is too big is that I use it all, 
then I started thinking about using restarts to make an interactive 
developer utility and realized it was Back to School time.

So my survey response:

   restarts

btw, Anybody else doing interactive utility software with nothing more 
than restarts?

kt

From: Pillsy
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <e814b152-80bb-44bf-9629-3c187ad28a79@u8g2000yqn.googlegroups.com>
On Apr 24, 8:56 am, Kenneth Tilton <·········@gmail.com> wrote:

> What is/are the big chunks of CL you have never used?

I've never used any of the more advanced functionality of the pretty
printer, or the table-oriented FORMAT stuff.

Also, they're not part of the standard, but I've never had cause to do
anything particularly involved with FFIs or the MOP.

Cheers,
Pillsy
From: Kenneth Tilton
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <49f1c052$0$22531$607ed4bc@cv.net>
Pillsy wrote:
> On Apr 24, 8:56 am, Kenneth Tilton <·········@gmail.com> wrote:
> 
>> What is/are the big chunks of CL you have never used?
> 
> I've never used any of the more advanced functionality of the pretty
> printer, or the table-oriented FORMAT stuff.

The pretty-printer! Don't get me started! I did a C-to-Lisp translator 
with that!!!

> 
> Also, they're not part of the standard, but I've never had cause to do
> anything particularly involved with FFIs or the MOP.

Oh, let's count those. The MOP at least.

kt
From: Slobodan Blazeski
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <1a9a362e-0aed-4ae3-8f16-2185d9416818@g1g2000yqh.googlegroups.com>
On Apr 24, 2:56 pm, Kenneth Tilton <·········@gmail.com> wrote:
> Lisp G*ds Only, for reasons obvious:
That excludes everybody beside you and  McCarthy ( who is meta god
BTW)
>
> What is/are the big chunks of CL you have never used? Series does not count.
>
> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
>
> So my survey response:
format and compound loop , but I'm actively avoiding them.
I don't think standrd is too big I'm actually pleasently surprised
every week when I find new functionality that solves my need exactly
like I wanted. Like the ANSI comitte was reading my mind and
anticipated my future needs.

bobi
http://slobodanblazeski.blogspot.com/
From: Tamas K Papp
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <75dt62F18209iU1@mid.individual.net>
On Fri, 24 Apr 2009 08:56:23 -0400, Kenneth Tilton wrote:

> Lisp G*ds Only, for reasons obvious:
> 
> What is/are the big chunks of CL you have never used? Series does not
> count.
> 
> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
> 
> So my survey response:
> 
>    restarts

I am certainly not a Lisp G*od, but I have found restarts extremely
useful for multivariate maximization/rootfinding.  Basic scenario is
this: take f(x): R^n->R^m, looking for argmax_x f(x) if m=1
(optimization), or x s.t. f(x)=0 if n=m (rootfinding).

There are some "general" algorithms for solving these, but they impose
some restrictions on f, and fail when f is not nice.  My solution was
to have the algorithm signal a condition (with enough information on
what happened) and specify some restarts ("I have hit a wall, what do
I do?").

Implementations in other languages (C, Fortran) deal with these things
in an ad-hoc manner (eg certain strategies to get out of bad places
are hardcoded), the CL solution is much more elegant.  In general,
conditions/restarts are useful for numerical algorithms.

Tamas
From: GP lisper
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <slrngv3v0g.ann.spambait@phoenix.clouddancer.com>
On 24 Apr 2009 13:29:38 GMT, <······@gmail.com> wrote:
>
> In general, conditions/restarts are useful for numerical algorithms.

An interesting insight.


-- 
Lisp:  Powering `Impossible Thoughts since 1958
From: Madhu
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <m3ab66mapt.fsf@moon.robolove.meer.net>
* Kenneth Tilton <·························@cv.net> :
Wrote on Fri, 24 Apr 2009 08:56:23 -0400:

| btw, Anybody else doing interactive utility software with nothing more
| than restarts?

I try to use them as much as I can.  They work well in `dungeon' program
scenarios --- In this context I've found Kaz's SUPER-RESTART-CASE useful
Also, you could try searching my simple CHOOSE-WITH-RESTART.

Some lisp implementations with their graphical debuggers have a nice UI
to invoke restarts.  But other lisps are not so great and on this whole
prevent their widespread use.  SLIME makes things a showstopper, by
truncating print the condition messages, adding intervening restarts,
and introducing outright bugs in CMUCL, so the :test condition to
control restart visibility will never work.

--
Madhu
From: Madhu
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <m37i1amal1.fsf@moon.robolove.meer.net>
* Kenneth Tilton <·························@cv.net> :
Wrote on Fri, 24 Apr 2009 08:56:23 -0400:

| btw, Anybody else doing interactive utility software with nothing more
| than restarts?

I try to use them as much as I can.  They work well in `dungeon' program
scenarios --- In this context I've found Kaz's SUPER-RESTART-CASE useful
Also, you could try searching my simple CHOOSE-WITH-RESTART.

Some lisp implementations with their graphical debuggers have a nice UI
to invoke restarts.  But other lisps are not so great and on the whole
this prevents their widespread use.  SLIME is a showstopper, with its
truncating printed condition messages, adding intervening restarts, and
introducing outright bugs in CMUCL, so the :test condition to control
restart visibility will never work.

--
Madhu
From: Kenneth Tilton
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <49f1cd7c$0$22510$607ed4bc@cv.net>
Madhu wrote:
> * Kenneth Tilton <·························@cv.net> :
> Wrote on Fri, 24 Apr 2009 08:56:23 -0400:
> 
> | btw, Anybody else doing interactive utility software with nothing more
> | than restarts?
> 
> I try to use them as much as I can.  They work well in `dungeon' program
> scenarios --- In this context I've found Kaz's SUPER-RESTART-CASE useful
> Also, you could try searching my simple CHOOSE-WITH-RESTART.
> 
> Some lisp implementations with their graphical debuggers have a nice UI
> to invoke restarts.  But other lisps are not so great and on the whole
> this prevents their widespread use.  SLIME is a showstopper, with its
> truncating printed condition messages, adding intervening restarts, and
> introducing outright bugs in CMUCL, so the :test condition to control
> restart visibility will never work.
> 
> --
> Madhu


Super, but... there /was/ a survey question!!!!!!!!

try to keep You People on topic for one message... <sigh>

kt
From: Scott Burson
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <8414c130-94c7-47a0-b0ae-fe440ff9132b@v1g2000prd.googlegroups.com>
On Apr 24, 5:56 am, Kenneth Tilton <·········@gmail.com> wrote:
> Lisp G*ds Only, for reasons obvious:
>
> What is/are the big chunks of CL you have never used? Series does not count.

I don't use LOOP on principle.  I have made only trivial use of the
MOP (a simple custom metaclass).

I think that's it for "big chunks", though there may be something I've
forgotten about.  Certainly there are smaller pieces I've never used
(have I ever defined a custom method combination type? don't think
so).

-- Scott
From: chthon
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <780b6ce2-154c-49f2-b3c8-6e7016462d4a@i28g2000prd.googlegroups.com>
On Apr 25, 7:17 am, Scott Burson <········@gmail.com> wrote:
> On Apr 24, 5:56 am, Kenneth Tilton <·········@gmail.com> wrote:
>
> > Lisp G*ds Only, for reasons obvious:
>
> > What is/are the big chunks of CL you have never used? Series does not count.
>
> I don't use LOOP on principle.  I have made only trivial use of the
> MOP (a simple custom metaclass).
>
> I think that's it for "big chunks", though there may be something I've
> forgotten about.  Certainly there are smaller pieces I've never used
> (have I ever defined a custom method combination type? don't think
> so).
>
> -- Scott

What do you use then instead of LOOP ? Smaller Lisp minds want to
know.

Regards,

Jurgen
From: Madhu
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <m31vrd3vip.fsf@moon.robolove.meer.net>
* chthon <····································@i28g2000prd.googlegroups.com> :
Wrote on Tue, 28 Apr 2009 02:53:55 -0700 (PDT):

| On Apr 25, 7:17 am, Scott Burson <> wrote:
|> I don't use LOOP on principle.  I have made only trivial use of the
|> MOP (a simple custom metaclass).

,----
| *  fset_1.1/Code/wb-trees.lisp
| 
| (defun WB-Set-Tree-Iterator-Canonicalize (iter)
|   (declare (optimize (speed 3) (safety 0)))
|   (loop
|     (let ((sp (svref iter 0))
`----

So Scott Burson _has_ used LOOP to implement the mapping iterators he
_does_ use. 

| What do you use then instead of LOOP ? Smaller Lisp minds want to
| know.


Myself, I slap this section on any copyright notices ALL my code.

;;;;  The software MAY NOT be rewritten or refactored by removing the
;;;;  use of LOOP or by the introduction of ITERATE or similar iteration
;;;;  macros without prior written permission.

--
Madhu (CL:LOOP fanatic :)
From: Slobodan Blazeski
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <6b0951ea-49f0-446a-8bcd-c575d7937a80@d7g2000prl.googlegroups.com>
On Apr 28, 12:47 pm, Madhu <·······@meer.net> wrote:
> * chthon <····································@i28g2000prd.googlegroups.com> :
> Wrote on Tue, 28 Apr 2009 02:53:55 -0700 (PDT):
>
> | On Apr 25, 7:17 am, Scott Burson <> wrote:
> |> I don't use LOOP on principle.  I have made only trivial use of the
> |> MOP (a simple custom metaclass).
>
> ,----
> | *  fset_1.1/Code/wb-trees.lisp
> |
> | (defun WB-Set-Tree-Iterator-Canonicalize (iter)
> |   (declare (optimize (speed 3) (safety 0)))
> |   (loop
> |     (let ((sp (svref iter 0))
> `----
>
> So Scott Burson _has_ used LOOP to implement the mapping iterators he
> _does_ use.
Thanks for noticing, will expell him from the group of compund loop
haters. :)
>
> | What do you use then instead of LOOP ? Smaller Lisp minds want to
> | know.
>
> Myself, I slap this section on any copyright notices ALL my code.
>
> ;;;;  The software MAY NOT be rewritten or refactored by removing the
> ;;;;  use of LOOP or by the introduction of ITERATE or similar iteration
> ;;;;  macros without prior written permission.
>
> --
> Madhu (CL:LOOP fanatic :)

Recursion and functional style usually results in a cleaner code,
though somewhat slower. For example see your and Maciej solutions
http://paste.lisp.org/display/54994 from thread
http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/740c43414b5b66b2/d8b4a79b69b724cf?hl=en&lnk=gst&q=yet+another+unification#d8b4a79b69b724cf
and compare it with mine below:
The code is shorter more than 3 times. 62 lines  Maciej,  62 Madhu, 19
Slobodan. I wonder if iterative solution could be cleaner then
recursion.

;Maciej
(defun collect (item/s)
  (let ((counter -1)
        (vars (make-hash-table))
        ticker-fn
        get-ticks-fn
        arity-fn)
    (labels ((tick (&optional idx)
               (funcall ticker-fn idx))
             (get-ticks ()
               (funcall get-ticks-fn))
             (arity ()
               (funcall arity-fn))
             (count* ()
               (incf counter))
             (has (item)
               (gethash item vars))
             (record (item idx)
               (setf (gethash item vars) idx))
             (make-ticker ()
               (let (ticks
                     (arity -1)
                     (old-ticker ticker-fn)
                     (old-get get-ticks-fn)
                     (old-arity arity-fn))
                   (setf ticker-fn
                         (lambda (&optional idx)
                           (let ((c (or idx (count*))))
                             (push c ticks)
                             (incf arity)
                             c)))
                   (setf get-ticks-fn
                        (lambda ()
                          (setf ticker-fn old-ticker
                                get-ticks-fn old-get
                                arity-fn old-arity)
                          ;; Push ourselves to the parent
                          (tick (car ticks))
                          (cdr ticks)))
                   (setf arity-fn
                         (lambda () arity))))
             (collect* (item/s more-p compound-p)
               (cond
                 ((atom item/s)
                  (if (and (not compound-p)
                           (has item/s))
                      ;; Non-unique occurence -- only record
                      ;; ourselves, but don't output anything
                      (null (tick (has item/s)))
                      (progn
                       (unless compound-p (record item/s (count*)))
                       (list
                        (list (tick (has item/s))
                              item/s
                              (var-str item/s)
                              (if more-p 0 (arity))
                              (unless more-p (get-ticks)))))))
                 ((listp item/s)
                  (make-ticker)
                  (iter (for (item . more-p) on (nreverse (cons 'list
item/s)))
                        (appending (collect* item more-p (not more-
p))))))))
      (make-ticker)
      (collect* item/s nil nil))))
;Madhu
(defun var-p (symbol)
  (eql (elt (symbol-name symbol) 0) #\?))
(deftype variable-term () '(satisfies var-p))
(defun str-p (symbol)
  (not (eql (elt (symbol-name symbol) 0) #\?)))
(deftype constant-term () '(satisfies str-p))
(defstruct composite-term str indices arity)
(defun main-functor (x)
  (etypecase x
    (cons (main-functor (car x)))
    (atom x)))
(defun slobodan-unify (xy &aux stack
		 (result (make-array 0 :fill-pointer t :adjustable t))
		 (var-table (make-hash-table))
		 (str-alist nil)
		 (fun-alist nil)
		 (counter 0))
  (flet ((rec (item)
	   (cond ((atom item)
		  (etypecase item
		    (composite-term
		     (push (cons (composite-term-str item) counter) fun-alist)
		     (vector-push-extend
		      (list (composite-term-str item)
			    counter :STR
			    (composite-term-arity item)
			    (mapcar (lambda (x)
				      (cond ((consp x)
					     (cdr (assoc
						   (main-functor x)
						   fun-alist)))
					    ((str-p x)
					     (cdr (assoc x str-alist)))
					    ((var-p x)
					     (gethash x var-table))))
				    (composite-term-indices item)))
		      result)
		     (incf counter))
		    (variable-term
		     (unless (gethash item var-table)
		       (setf (gethash item var-table) counter)
		       (vector-push-extend (list item counter :VAR 0 nil)
					   result)
		       (incf counter)))
		    (constant-term
		     (push (cons item counter) str-alist)
		     (vector-push-extend (list item counter :STR 0 nil)
					 result)
		     (incf counter))))
		 (t
		  (assert (atom (car item)))
		  (assert (str-p (car item)))
		  (push (make-composite-term :str (car item)
					     :indices (cdr item)
					     :arity (length (cdr item)))
			stack)
		  (loop for elem in (cdr item) do (push elem stack))))))
    (assert (= (length xy) 2))
    (rec (car xy))
    (rec (cadr xy))
    (loop while stack do (rec (pop stack)))
    result))
;Slobodan
(defun exist? (key map)
  (nth-value 1 (gethash key map)))
(defun utable1 (x)
  (let ((i -1) res (vars (make-hash-table)))
    (labels ((add-term (y arity components)
               (if (and (var? y) (present? y vars))
                 (gethash y vars)
                 (progn
                   (push (list (incf i) y (var-str y)
                               arity components) res)
                   (setf (gethash y vars) i))))
             (add-list (z)
               (reverse (mapcar #'(lambda (e) (at e)) z)))
             (at (y)
               (if (consp y)
                 (add-term (car y) (length (cdr y))
                   (reverse (mapcar #'(lambda (e) (at e)) (reverse
(cdr y)))))
                 (add-term y 0 nil))))
      (values (at (cadr x)) (at (car x)) (reverse res)))))
From: Slobodan Blazeski
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <bb507242-ce12-487c-b4f5-670eccfc02e9@j9g2000prh.googlegroups.com>
On Apr 28, 1:59 pm, Slobodan Blazeski <·················@gmail.com>
wrote:
> On Apr 28, 12:47 pm, Madhu <·······@meer.net> wrote:
> > | What do you use then instead of LOOP ? Smaller Lisp minds want to
> > | know.
>
> > Myself, I slap this section on any copyright notices ALL my code.
>
> > ;;;;  The software MAY NOT be rewritten or refactored by removing the
> > ;;;;  use of LOOP or by the introduction of ITERATE or similar iteration
> > ;;;;  macros without prior written permission.
>
> > --
> > Madhu (CL:LOOP fanatic :)
>
> Recursion and functional style usually results in a cleaner code,
> though somewhat slower. For example see your and Maciej solutionshttp://paste.lisp.org/display/54994from threadhttp://groups.google.com/group/comp.lang.lisp/browse_thread/thread/74...
> and compare it with mine below:
> The code is shorter more than 3 times. 62 lines  Maciej,  62 Madhu, 19
Sorry I mean Slobodan 17, one fucntion add-list was not used. That
makes it almost 4 times shorter (~3.65 times actually).
There should be a huge gain in efficiency to compensate for such loss
of clarity.
(defun exist? (key map)
  (nth-value 1 (gethash key map)))
(defun utable1 (x)
  (let ((i -1) res (vars (make-hash-table)))
    (labels ((add-term (y arity components)
               (if (and (var? y) (present? y vars))
                 (gethash y vars)
                 (progn
                   (push (list (incf i) y (var-str y)
                               arity components) res)
                   (setf (gethash y vars) i))))
             (at (y)
               (if (consp y)
                 (add-term (car y) (length (cdr y))
                   (reverse (mapcar #'(lambda (e) (at e)) (reverse
(cdr y)))))
                 (add-term y 0 nil))))
      (values (at (cadr x)) (at (car x)) (reverse res)))))
From: John Thingstad
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <op.us4b23mfut4oq5@pandora>
På Tue, 28 Apr 2009 14:03:44 +0200, skrev Slobodan Blazeski  
<·················@gmail.com>:

> On Apr 28, 1:59 pm, Slobodan Blazeski <·················@gmail.com>
> wrote:
>> On Apr 28, 12:47 pm, Madhu <·······@meer.net> wrote:
>> > | What do you use then instead of LOOP ? Smaller Lisp minds want to
>> > | know.
>>
>> > Myself, I slap this section on any copyright notices ALL my code.
>>
>> > ;;;;  The software MAY NOT be rewritten or refactored by removing the
>> > ;;;;  use of LOOP or by the introduction of ITERATE or similar  
>> iteration
>> > ;;;;  macros without prior written permission.
>>
>> > --
>> > Madhu (CL:LOOP fanatic :)
>>
>> Recursion and functional style usually results in a cleaner code,
>> though somewhat slower. For example see your and Maciej  
>> solutionshttp://paste.lisp.org/display/54994from  
>> threadhttp://groups.google.com/group/comp.lang.lisp/browse_thread/thread/74...
>> and compare it with mine below:
>> The code is shorter more than 3 times. 62 lines  Maciej,  62 Madhu, 19
> Sorry I mean Slobodan 17, one fucntion add-list was not used. That
> makes it almost 4 times shorter (~3.65 times actually).
> There should be a huge gain in efficiency to compensate for such loss
> of clarity.
> (defun exist? (key map)
>   (nth-value 1 (gethash key map)))
> (defun utable1 (x)
>   (let ((i -1) res (vars (make-hash-table)))
>     (labels ((add-term (y arity components)
>                (if (and (var? y) (present? y vars))
>                  (gethash y vars)
>                  (progn
>                    (push (list (incf i) y (var-str y)
>                                arity components) res)
>                    (setf (gethash y vars) i))))
>              (at (y)
>                (if (consp y)
>                  (add-term (car y) (length (cdr y))
>                    (reverse (mapcar #'(lambda (e) (at e)) (reverse
> (cdr y)))))
>                  (add-term y 0 nil))))
>       (values (at (cadr x)) (at (car x)) (reverse res)))))

loss my ass, That is much clearer!

-----------------------
John Thingstad
From: Slobodan Blazeski
Subject: Clarity
Date: 
Message-ID: <6d572d19-9252-4fe8-b30e-04cfc918774a@w31g2000prd.googlegroups.com>
On Apr 29, 12:43 am, "John Thingstad" <·······@online.no> wrote:
> På Tue, 28 Apr 2009 14:03:44 +0200, skrev Slobodan Blazeski  
> <·················@gmail.com>:
>
>
>
>
>
> > On Apr 28, 1:59 pm, Slobodan Blazeski <·················@gmail.com>
> > wrote:
> >> On Apr 28, 12:47 pm, Madhu <·······@meer.net> wrote:
> >> > | What do you use then instead of LOOP ? Smaller Lisp minds want to
> >> > | know.
>
> >> > Myself, I slap this section on any copyright notices ALL my code.
>
> >> > ;;;;  The software MAY NOT be rewritten or refactored by removing the
> >> > ;;;;  use of LOOP or by the introduction of ITERATE or similar  
> >> iteration
> >> > ;;;;  macros without prior written permission.
>
> >> > --
> >> > Madhu (CL:LOOP fanatic :)
>
> >> Recursion and functional style usually results in a cleaner code,
> >> though somewhat slower. For example see your and Maciej  
> >> solutionshttp://paste.lisp.org/display/54994from 
> >> threadhttp://groups.google.com/group/comp.lang.lisp/browse_thread/thread/74...
> >> and compare it with mine below:
> >> The code is shorter more than 3 times. 62 lines  Maciej,  62 Madhu, 19
> > Sorry I mean Slobodan 17, one fucntion add-list was not used. That
> > makes it almost 4 times shorter (~3.65 times actually).
> > There should be a huge gain in efficiency to compensate for such loss
> > of clarity.
> > (defun exist? (key map)
> >   (nth-value 1 (gethash key map)))
> > (defun utable1 (x)
> >   (let ((i -1) res (vars (make-hash-table)))
> >     (labels ((add-term (y arity components)
> >                (if (and (var? y) (present? y vars))
> >                  (gethash y vars)
> >                  (progn
> >                    (push (list (incf i) y (var-str y)
> >                                arity components) res)
> >                    (setf (gethash y vars) i))))
> >              (at (y)
> >                (if (consp y)
> >                  (add-term (car y) (length (cdr y))
> >                    (reverse (mapcar #'(lambda (e) (at e)) (reverse
> > (cdr y)))))
> >                  (add-term y 0 nil))))
> >       (values (at (cadr x)) (at (car x)) (reverse res)))))
>
> loss my ass, That is much clearer!

I know it still sucks, but I can't make it  suck less. If you have any
ideas for improvements I'm all ears er eyes.
Actually wait until you see step 2 of the algorithm implementation,
that's what I call ugly.

cheers
bobi
http://slobodanblazeski.blogspot.com/
>
> -----------------------
> John Thingstad
From: John Thingstad
Subject: Re: Clarity
Date: 
Message-ID: <op.us45xlofut4oq5@pandora>
På Wed, 29 Apr 2009 08:15:57 +0200, skrev Slobodan Blazeski  
<·················@gmail.com>:

>
> I know it still sucks, but I can't make it  suck less. If you have any
> ideas for improvements I'm all ears er eyes.
> Actually wait until you see step 2 of the algorithm implementation,
> that's what I call ugly.
>

You are being overly critical (which is a good thing), but actually your  
code (the bit's I have seem) is fine.

---------------------
John Thingstad
From: chthon
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <9dcb1a24-b42c-4f33-b142-0ab13590ed26@b6g2000pre.googlegroups.com>
On Apr 28, 1:59 pm, Slobodan Blazeski <·················@gmail.com>
wrote:
> On Apr 28, 12:47 pm, Madhu <·······@meer.net> wrote:
>
> > * chthon <····································@i28g2000prd.googlegroups.com> :
> > Wrote on Tue, 28 Apr 2009 02:53:55 -0700 (PDT):
>
> > | On Apr 25, 7:17 am, Scott Burson <> wrote:
> > |> I don't use LOOP on principle.  I have made only trivial use of the
> > |> MOP (a simple custom metaclass).
>
> > ,----
> > | *  fset_1.1/Code/wb-trees.lisp
> > |
> > | (defun WB-Set-Tree-Iterator-Canonicalize (iter)
> > |   (declare (optimize (speed 3) (safety 0)))
> > |   (loop
> > |     (let ((sp (svref iter 0))
> > `----
>
> > So Scott Burson _has_ used LOOP to implement the mapping iterators he
> > _does_ use.
>
> Thanks for noticing, will expell him from the group of compund loop
> haters. :)
>
>
>
> > | What do you use then instead of LOOP ? Smaller Lisp minds want to
> > | know.
>
> > Myself, I slap this section on any copyright notices ALL my code.
>
> > ;;;;  The software MAY NOT be rewritten or refactored by removing the
> > ;;;;  use of LOOP or by the introduction of ITERATE or similar iteration
> > ;;;;  macros without prior written permission.
>
> > --
> > Madhu (CL:LOOP fanatic :)
>
> Recursion and functional style usually results in a cleaner code,
> though somewhat slower. For example see your and Maciej solutionshttp://paste.lisp.org/display/54994from threadhttp://groups.google.com/group/comp.lang.lisp/browse_thread/thread/74...
> and compare it with mine below:
> The code is shorter more than 3 times. 62 lines  Maciej,  62 Madhu, 19
> Slobodan. I wonder if iterative solution could be cleaner then
> recursion.
>
> ;Maciej
> (defun collect (item/s)
>   (let ((counter -1)
>         (vars (make-hash-table))
>         ticker-fn
>         get-ticks-fn
>         arity-fn)
>     (labels ((tick (&optional idx)
>                (funcall ticker-fn idx))
>              (get-ticks ()
>                (funcall get-ticks-fn))
>              (arity ()
>                (funcall arity-fn))
>              (count* ()
>                (incf counter))
>              (has (item)
>                (gethash item vars))
>              (record (item idx)
>                (setf (gethash item vars) idx))
>              (make-ticker ()
>                (let (ticks
>                      (arity -1)
>                      (old-ticker ticker-fn)
>                      (old-get get-ticks-fn)
>                      (old-arity arity-fn))
>                    (setf ticker-fn
>                          (lambda (&optional idx)
>                            (let ((c (or idx (count*))))
>                              (push c ticks)
>                              (incf arity)
>                              c)))
>                    (setf get-ticks-fn
>                         (lambda ()
>                           (setf ticker-fn old-ticker
>                                 get-ticks-fn old-get
>                                 arity-fn old-arity)
>                           ;; Push ourselves to the parent
>                           (tick (car ticks))
>                           (cdr ticks)))
>                    (setf arity-fn
>                          (lambda () arity))))
>              (collect* (item/s more-p compound-p)
>                (cond
>                  ((atom item/s)
>                   (if (and (not compound-p)
>                            (has item/s))
>                       ;; Non-unique occurence -- only record
>                       ;; ourselves, but don't output anything
>                       (null (tick (has item/s)))
>                       (progn
>                        (unless compound-p (record item/s (count*)))
>                        (list
>                         (list (tick (has item/s))
>                               item/s
>                               (var-str item/s)
>                               (if more-p 0 (arity))
>                               (unless more-p (get-ticks)))))))
>                  ((listp item/s)
>                   (make-ticker)
>                   (iter (for (item . more-p) on (nreverse (cons 'list
> item/s)))
>                         (appending (collect* item more-p (not more-
> p))))))))
>       (make-ticker)
>       (collect* item/s nil nil))))
> ;Madhu
> (defun var-p (symbol)
>   (eql (elt (symbol-name symbol) 0) #\?))
> (deftype variable-term () '(satisfies var-p))
> (defun str-p (symbol)
>   (not (eql (elt (symbol-name symbol) 0) #\?)))
> (deftype constant-term () '(satisfies str-p))
> (defstruct composite-term str indices arity)
> (defun main-functor (x)
>   (etypecase x
>     (cons (main-functor (car x)))
>     (atom x)))
> (defun slobodan-unify (xy &aux stack
>                  (result (make-array 0 :fill-pointer t :adjustable t))
>                  (var-table (make-hash-table))
>                  (str-alist nil)
>                  (fun-alist nil)
>                  (counter 0))
>   (flet ((rec (item)
>            (cond ((atom item)
>                   (etypecase item
>                     (composite-term
>                      (push (cons (composite-term-str item) counter) fun-alist)
>                      (vector-push-extend
>                       (list (composite-term-str item)
>                             counter :STR
>                             (composite-term-arity item)
>                             (mapcar (lambda (x)
>                                       (cond ((consp x)
>                                              (cdr (assoc
>                                                    (main-functor x)
>                                                    fun-alist)))
>                                             ((str-p x)
>                                              (cdr (assoc x str-alist)))
>                                             ((var-p x)
>                                              (gethash x var-table))))
>                                     (composite-term-indices item)))
>                       result)
>                      (incf counter))
>                     (variable-term
>                      (unless (gethash item var-table)
>                        (setf (gethash item var-table) counter)
>                        (vector-push-extend (list item counter :VAR 0 nil)
>                                            result)
>                        (incf counter)))
>                     (constant-term
>                      (push (cons item counter) str-alist)
>                      (vector-push-extend (list item counter :STR 0 nil)
>                                          result)
>                      (incf counter))))
>                  (t
>                   (assert (atom (car item)))
>                   (assert (str-p (car item)))
>                   (push (make-composite-term :str (car item)
>                                              :indices (cdr item)
>                                              :arity (length (cdr item)))
>                         stack)
>                   (loop for elem in (cdr item) do (push elem stack))))))
>     (assert (= (length xy) 2))
>     (rec (car xy))
>     (rec (cadr xy))
>     (loop while stack do (rec (pop stack)))
>     result))
> ;Slobodan
> (defun exist? (key map)
>   (nth-value 1 (gethash key map)))
> (defun utable1 (x)
>   (let ((i -1) res (vars (make-hash-table)))
>     (labels ((add-term (y arity components)
>                (if (and (var? y) (present? y vars))
>                  (gethash y vars)
>                  (progn
>                    (push (list (incf i) y (var-str y)
>                                arity components) res)
>                    (setf (gethash y vars) i))))
>              (add-list (z)
>                (reverse (mapcar #'(lambda (e) (at e)) z)))
>              (at (y)
>                (if (consp y)
>                  (add-term (car y) (length (cdr y))
>                    (reverse (mapcar #'(lambda (e) (at e)) (reverse
> (cdr y)))))
>                  (add-term y 0 nil))))
>       (values (at (cadr x)) (at (car x)) (reverse res)))))

Yes, know about recursion (I did read parts of SICP), but since CL
implementations are not required to implement tail recursion, one
cannot expect that all iterative constructs can be replaced by
recursion.

If I program in Scheme then it is almost natural to use tail
recursion, while in Common Lisp, generally that can not be the case,
since this is implementation dependent. So I use LOOP fairly often.

Regards,

Jurgen
From: gugamilare
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <14fc8520-2a61-4ddc-b983-3cc1092878b1@j18g2000prm.googlegroups.com>
On 29 abr, 06:29, chthon <··············@pandora.be> wrote:
>
> Yes, know about recursion (I did read parts of SICP), but since CL
> implementations are not required to implement tail recursion, one
> cannot expect that all iterative constructs can be replaced by
> recursion.
>
> If I program in Scheme then it is almost natural to use tail
> recursion, while in Common Lisp, generally that can not be the case,
> since this is implementation dependent. So I use LOOP fairly often.

People keep saying that tail recursion in CL is implementation
dependent, but the only implementation that I tested that doesn't have
tail call optimization is ECL, and I expect that to be changed. Even
Clisp, which is not optimized, has this optimization if you compile
the function.
>
> Regards,
>
> Jurgen
From: Scott Burson
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <b89441a5-1cbc-4ed3-92e5-c4a7ad4a63bd@b7g2000pre.googlegroups.com>
On Apr 29, 5:36 pm, gugamilare <··········@gmail.com> wrote:
>
> People keep saying that tail recursion in CL is implementation
> dependent, but the only implementation that I tested that doesn't have
> tail call optimization is ECL, and I expect that to be changed. Even
> Clisp, which is not optimized, has this optimization if you compile
> the function.

Whoa, careful.  In Allegro -- and LispWorks also? -- TCO is done only
for self-calls and calls to local functions.  So if you have a single
LABELS expression that defines several functions they can tail-call
one another, but top-level functions do not, except for self-calls.
Or something like that; it's definitely not done in every possible
situation, as in the CMUCL family.

I still think that rather than using TCO whenever possible, it would
be better to allow the user to declare sets of mutually tail-recursive
top-level functions, and to have calls outside that set not be subject
to TCO.  This would allow you to do things like code an FSA as a set
of top-level functions, while not harming debuggability in the normal
case.

-- Scott
From: Rob Warnock
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <b5-dnWp-TIfEZGXUnZ2dnUVZ_vmdnZ2d@speakeasy.net>
gugamilare  <··········@gmail.com> wrote:
+---------------
| chthon <··············@pandora.be> wrote:
| > If I program in Scheme then it is almost natural to use tail
| > recursion, while in Common Lisp, generally that can not be the case,
| > since this is implementation dependent. So I use LOOP fairly often.
| 
| People keep saying that tail recursion in CL is implementation
| dependent, but the only implementation that I tested that doesn't have
| tail call optimization is ECL, and I expect that to be changed. Even
| Clisp, which is not optimized, has this optimization if you compile
| the function.
+---------------

Careful! What you say is true *only* in the absence of live bindings
for dynamic variables or live dynamic contexts such as UNWIND-PROTECT,
WITHOUT-ERRORS, HANDLER-BIND, HANDLER-CASE, CATCH, etc., etc., etc.
Even CL implementations which routinely do TCO for "simple" tail calls
generally cannot do TCO across such contours!! Note that the non-TCO'able
case could be as simple as this:

    > (defun foo (*standard-output*)
        (format t "This was *not* a tail call of FORMAT!!"))

    FOO
    > (with-output-to-string (s)
	(foo s))

    "This was *not* a tail call of FORMAT!!"
    > 


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: gugamilare
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <9a0df274-00cf-47a8-a0f6-e2a846b52da7@x29g2000prf.googlegroups.com>
On 29 abr, 22:05, ····@rpw3.org (Rob Warnock) wrote:
> gugamilare  <··········@gmail.com> wrote:
>
> +---------------| chthon <··············@pandora.be> wrote:
>
> | > If I program in Scheme then it is almost natural to use tail
> | > recursion, while in Common Lisp, generally that can not be the case,
> | > since this is implementation dependent. So I use LOOP fairly often.
> |
> | People keep saying that tail recursion in CL is implementation
> | dependent, but the only implementation that I tested that doesn't have
> | tail call optimization is ECL, and I expect that to be changed. Even
> | Clisp, which is not optimized, has this optimization if you compile
> | the function.
> +---------------
>
> Careful! What you say is true *only* in the absence of live bindings
> for dynamic variables or live dynamic contexts such as UNWIND-PROTECT,
> WITHOUT-ERRORS, HANDLER-BIND, HANDLER-CASE, CATCH, etc., etc., etc.
> Even CL implementations which routinely do TCO for "simple" tail calls
> generally cannot do TCO across such contours!! Note that the non-TCO'able
> case could be as simple as this:
>
>     > (defun foo (*standard-output*)
>         (format t "This was *not* a tail call of FORMAT!!"))
>
>     FOO
>     > (with-output-to-string (s)
>         (foo s))
>
>     "This was *not* a tail call of FORMAT!!"
>     >
>
> -Rob
>
> -----
> Rob Warnock                     <····@rpw3.org>
> 627 26th Avenue                 <URL:http://rpw3.org/>
> San Mateo, CA 94403             (650)572-2607

Ok, I've missed the special cases. But most of the cases were you need
loops, you won't need to rebind special variables.
From: Pascal Costanza
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <75tia1F1alcnsU1@mid.individual.net>
Rob Warnock wrote:
> gugamilare  <··········@gmail.com> wrote:
> +---------------
> | chthon <··············@pandora.be> wrote:
> | > If I program in Scheme then it is almost natural to use tail
> | > recursion, while in Common Lisp, generally that can not be the case,
> | > since this is implementation dependent. So I use LOOP fairly often.
> | 
> | People keep saying that tail recursion in CL is implementation
> | dependent, but the only implementation that I tested that doesn't have
> | tail call optimization is ECL, and I expect that to be changed. Even
> | Clisp, which is not optimized, has this optimization if you compile
> | the function.
> +---------------
> 
> Careful! What you say is true *only* in the absence of live bindings
> for dynamic variables or live dynamic contexts such as UNWIND-PROTECT,
> WITHOUT-ERRORS, HANDLER-BIND, HANDLER-CASE, CATCH, etc., etc., etc.
> Even CL implementations which routinely do TCO for "simple" tail calls
> generally cannot do TCO across such contours!! 

A particularly sad case is that tail calls in CLOS methods are usually 
never optimized. The reason is that the list of next methods typically 
seems to be bound to an internal special variable, where it could 
actually just be passed as a (lexical) parameter to the method 
functions. The latter is also how the CLOS MOP specifies it, but I am 
not aware of any CLOS implementation that sticks to this particular part 
of the spec. (If they did, tail call optimization would be possible for 
CLOS.)


Pascal

-- 
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Costanza
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <763a4sF1asm2kU1@mid.individual.net>
Pascal Costanza wrote:
> Rob Warnock wrote:
>> gugamilare  <··········@gmail.com> wrote:
>> +---------------
>> | chthon <··············@pandora.be> wrote:
>> | > If I program in Scheme then it is almost natural to use tail
>> | > recursion, while in Common Lisp, generally that can not be the case,
>> | > since this is implementation dependent. So I use LOOP fairly often.
>> | | People keep saying that tail recursion in CL is implementation
>> | dependent, but the only implementation that I tested that doesn't have
>> | tail call optimization is ECL, and I expect that to be changed. Even
>> | Clisp, which is not optimized, has this optimization if you compile
>> | the function.
>> +---------------
>>
>> Careful! What you say is true *only* in the absence of live bindings
>> for dynamic variables or live dynamic contexts such as UNWIND-PROTECT,
>> WITHOUT-ERRORS, HANDLER-BIND, HANDLER-CASE, CATCH, etc., etc., etc.
>> Even CL implementations which routinely do TCO for "simple" tail calls
>> generally cannot do TCO across such contours!! 
> 
> A particularly sad case is that tail calls in CLOS methods are usually 
> never optimized. The reason is that the list of next methods typically 
> seems to be bound to an internal special variable, where it could 
> actually just be passed as a (lexical) parameter to the method 
> functions. The latter is also how the CLOS MOP specifies it, but I am 
> not aware of any CLOS implementation that sticks to this particular part 
> of the spec. (If they did, tail call optimization would be possible for 
> CLOS.)

I have to correct my statement, due to some feedback I got by private email.

I made some small tests on some Common Lisp implementations. It seems 
that Clozure, CMUCL, LispWorks and SBCL optimize tail calls in CLOS 
methods, while Allegro and clisp don't. (It was a very simple test, so 
take this with a grain of salt.)


Pascal


-- 
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: ·····@franz.com
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <4d6a13f6-9b56-4b53-9715-3521067d47d6@w35g2000prg.googlegroups.com>
On May 2, 9:19 am, Pascal Costanza <····@p-cos.net> wrote:

> > A particularly sad case is that tail calls in CLOS methods are usually
> > never optimized. The reason is that the list of next methods typically
> > seems to be bound to an internal special variable, where it could
> > actually just be passed as a (lexical) parameter to the method
> > functions. The latter is also how the CLOS MOP specifies it, but I am
> > not aware of any CLOS implementation that sticks to this particular part
> > of the spec. (If they did, tail call optimization would be possible for
> > CLOS.)
>
> I have to correct my statement, due to some feedback I got by private email.
>
> I made some small tests on some Common Lisp implementations. It seems
> that Clozure, CMUCL, LispWorks and SBCL optimize tail calls in CLOS
> methods, while Allegro and clisp don't. (It was a very simple test, so
> take this with a grain of salt.)

Can you please make your test public?  I'd like to respond.  My own
simple test places Allegro CL in the first category, though of course
there may be reasons why you get different results.  Tail merging
isn't a foregone conclusion in any setting, but is parameterized
differently in different CL implementations.

Duane

Transcript for Allegro CL 8.1 (x86-64):

CL-USER(1): (shell "cat foo.cl")
(eval-when (:compile-toplevel)
  (declaim (optimize (safety 0) ;; only for simplicity
		     speed
		     (debug 0))))

(defmethod foo ((x integer) (y integer))
  (bar x y))
0
CL-USER(2): :cl foo
;;; Compiling file foo.cl
;;; Writing fasl file foo.fasl
;;; Fasl write complete
; Fast loading /net/gemini/home/duane/foo.fasl
Warning: While compiling these undefined functions were referenced:
         BAR from position 120 in foo.cl
CL-USER(3): (inspect (mop:generic-function-methods #'foo))
A NEW proper list @ #x10009e4ac1 with 1 element
   0-> #<STANDARD-METHOD FOO (INTEGER INTEGER)>
[1i] CL-USER(4): :i 0
A NEW STANDARD-METHOD @ #x10009626b2 = #<STANDARD-METHOD
                                         FOO
                                         (INTEGER INTEGER)>
   0 Class --------> #<STANDARD-CLASS STANDARD-METHOD>
   1 PLIST --------> The symbol NIL
   2 GENERIC-FUNCTION -> #<STANDARD-GENERIC-FUNCTION FOO>
   3 SPECIALIZERS -> (#1=# #1#), a proper list with 2 elements
   4 QUALIFIERS ---> The symbol NIL
   5 LAMBDA-LIST --> ((X INTEGER) (Y INTEGER)), a proper list with 2
elements
   6 FUNCTION -----> #<Function (METHOD FOO (INTEGER INTEGER))>
[1i] CL-USER(5): :i 6
A NEW #<Function (METHOD FOO (INTEGER INTEGER))>
  lambda-list: NIL
   0 excl-type ----> Bit field: #x88
   1 flags --------> Bit field: #xa8
   2 start --------> Bit field: #x00002aaaacbc6208
   3 hash ---------> Bit field: #x0000000000008508
   4 symdef -------> (((METHOD) . FOO) ...), a proper list with 3
elements
   5 code ---------> short simple CODE vector (12) = #(35657 13934
25599 ...)
   6 formals ------> The symbol NIL
   7 cframe-size --> fixnum 0 [#x0000000000000000]
   8 immed-args ---> fixnum 0 [#x0000000000000000]
   9 locals -------> fixnum 0 [#x0000000000000000]
  10 <constant> ---> The symbol BAR
[1i] CL-USER(6): (disassemble *)
;; disassembly of #<Function (METHOD FOO (INTEGER INTEGER))>
;; formals: [none]
;; constant vector:
0: BAR

;; code start: #x2aaaacbc6208:
   0: 49 8b 6e 36    movq	rbp,[r14+54]  ; BAR
   4: ff 63 d0       jmp	*[rbx-48]
   7: 90             nop
[1i] CL-USER(7):
From: Pascal Costanza
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <763qjkF1an0saU1@mid.individual.net>
·····@franz.com wrote:
> On May 2, 9:19 am, Pascal Costanza <····@p-cos.net> wrote:
> 
>>> A particularly sad case is that tail calls in CLOS methods are usually
>>> never optimized. The reason is that the list of next methods typically
>>> seems to be bound to an internal special variable, where it could
>>> actually just be passed as a (lexical) parameter to the method
>>> functions. The latter is also how the CLOS MOP specifies it, but I am
>>> not aware of any CLOS implementation that sticks to this particular part
>>> of the spec. (If they did, tail call optimization would be possible for
>>> CLOS.)
>> I have to correct my statement, due to some feedback I got by private email.
>>
>> I made some small tests on some Common Lisp implementations. It seems
>> that Clozure, CMUCL, LispWorks and SBCL optimize tail calls in CLOS
>> methods, while Allegro and clisp don't. (It was a very simple test, so
>> take this with a grain of salt.)
> 
> Can you please make your test public?  I'd like to respond.  My own
> simple test places Allegro CL in the first category, though of course
> there may be reasons why you get different results. 

Sure, no problem. It might as well be that I just misunderstand what I see.

Here is the code:

(declaim (optimize (speed 3) (space 3) (safety 0) (debug 0)))

(defmethod foo (x)
   (if (next-method-p)
       (call-next-method)
       (bar x)))

(defun bar (x) (error "baz"))

The invocation of next-method-p and call-next-method is to ensure that 
the compiler doesn't optimize the list of next methods away.

Here is a session:

CL-USER(1): (compile-file "test")
;;; Compiling file test.lisp
; While compiling BAR:
Warning: Variable X is never used.
;;; Writing fasl file test.fasl
;;; Fasl write complete
#P"/Users/costanza/Muell/test.fasl"
T
NIL
CL-USER(2): (load "test")
; Fast loading /Users/costanza/Muell/test.fasl
T
CL-USER(3): (foo 3)
Error: baz

Restart actions (select using :continue):
  0: Return to Top Level (an "abort" restart).
  1: Abort entirely from this (lisp) process.
[1] CL-USER(4): :bt
Evaluation stack:

BAR <-
   (:INTERNAL (:EFFECTIVE-METHOD 1 NIL ...) 0) <- EVAL <-
   TPL:TOP-LEVEL-READ-EVAL-PRINT-LOOP <- TPL:START-INTERACTIVE-TOP-LEVEL


...so there seems to be a method for foo on the stack, right?


Pascal

-- 
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Juanjo
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <e9ef5468-a3f8-49b5-a1d3-dafff88b4c49@s20g2000yqh.googlegroups.com>
On Apr 30, 2:36 am, gugamilare <··········@gmail.com> wrote:
> People keep saying that tail recursion in CL is implementation
> dependent, but the only implementation that I tested that doesn't have
> tail call optimization is ECL, and I expect that to be changed.

ECL does not have tail call optimization for _interpreted_ code.
Compiled code, for suitable optimization speeds, does implement tail
self-call optimization. It can not implement that optimization for
calls to other functions because it depends on C compilers --- well
actually gcc may do that optimization for you also under suitable
optimization parameters.

Juanjo
From: Scott Burson
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <8ce8416b-3893-4d66-b615-976eb3c37e1d@t36g2000prt.googlegroups.com>
On Apr 28, 3:47 am, Madhu <·······@meer.net> wrote:
> * chthon <····································@i28g2000prd.googlegroups.com> :
> Wrote on Tue, 28 Apr 2009 02:53:55 -0700 (PDT):
>
> | On Apr 25, 7:17 am, Scott Burson <> wrote:
> |> I don't use LOOP on principle.  I have made only trivial use of the
> |> MOP (a simple custom metaclass).
>
> ,----
> | *  fset_1.1/Code/wb-trees.lisp
> |
> | (defun WB-Set-Tree-Iterator-Canonicalize (iter)
> |   (declare (optimize (speed 3) (safety 0)))
> |   (loop
> |     (let ((sp (svref iter 0))
> `----
>
> So Scott Burson _has_ used LOOP to implement the mapping iterators he
> _does_ use.

Only the trivial CLtL1 form, to which I have no objection.  With no
keywords, it's just a do-forever loop.  (I think when most people
speak of LOOP they mean the nontrivial form, but I suppose I should
have noted the exception.)

-- Scott
From: Scott Burson
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <7cbf9b76-441e-4fb0-b97e-f5099668d998@s38g2000prg.googlegroups.com>
On Apr 28, 2:53 am, chthon <··············@pandora.be> wrote:
>
> What do you use then instead of LOOP ? Smaller Lisp minds want to
> know.

The first question is whether the loop is to be imperative (passes
through a series of states having some side-effect) or functional
(computes a value of some kind).  This is a stylistic question;
functional iteration can always be done imperatively, but is often
clearer when expressed functionally.  On the other hand, some
iterations are imperative by their nature, and seem too hard to me to
express functionally (I guess Haskell users find ways).  I like the
functional style a lot, which is why I created FSet, and I probably
use it more than most CL users, but if an iteration seems naturally
imperative I don't usually fight to make it functional.

So, for imperative loops where the iterations are in one-to-one
correspondence with the members of a specific collection, I use DOLIST
or (with FSet) DO-SET, DO-SEQ, or DO-MAP.  In more complex situations,
where the iterations are not in one-to-one correspondence with any set
known in advance, I will use one of DO (yes I really use good old DO),
WHILE (my own macro which expands to DO in the obvious way), or (as
Madhu helpfully pointed out) the trivial CLtL1 form of LOOP.  This
form of LOOP has no keywords but just loops forever; it is useful in
cases where the exit test is not naturally placed at the top of the
loop, e.g.:

  (loop
    (let ((foo ...))
      (when (terminate? foo)
        (return))
      (do-something-with foo)))

For functional iteration there are really three sets of important
functions.  The Common Lisp builtins are MAPCAR, REDUCE, and REMOVE-IF-
NOT.  With my FSet types there are IMAGE (similar to MAPCAR but not
the same), REDUCE again, and FILTER (like REMOVE-IF-NOT).  And finally
there is my macro GMAP which combines functionality from all these and
more.  I use all three of these sets freely in my own code, which
probably is not the best thing from the point of view of the poor sod
who has to read it :)

I've mentioned GMAP here once or twice.  I'm quite fond of it, but
I've never been able to interest anyone else in using it, AFAIK.  It's
somewhat like Waters' Series package, but far simpler in both concept
and implementation.  Nevertheless, in my experience, it handles a lot
of cases very elegantly.

All GMAP does is generalize CL:MAP in two ways: first by providing an
extensible set of result constructors, and secondly by providing an
extensible set of argument generators.  So where CL:MAP can only
generate arguments to the mapped function by iterating over sequences,
and can only produce some sequence type as its result, GMAP (being a
macro) has syntax that lets you specify how to generate each argument,
and also how to collect up the results (so it combines the
functionality of MAP and REDUCE).

You can find GMAP and FSet, respectively, at:

http://common-lisp.net/project/misc-extensions/
http://common-lisp.net/project/fset/

I would give some examples here, but I'm out of time at the moment.

-- Scott
From: Scott Burson
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <172cefc0-9075-433e-86fb-cb9314a4a264@b6g2000pre.googlegroups.com>
On Apr 28, 7:21 pm, Scott Burson <········@gmail.com> wrote:
[...]

Whew, it finally showed up!

-- Scott
From: Madhu
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <m34ow58uqd.fsf@moon.robolove.meer.net>
* Scott Burson Wrote on Tue, 28 Apr 2009 19:21:02 -0700 (PDT):

| On Apr 28, 2:53 am, chthon <··············@pandora.be> wrote:
|>
|> What do you use then instead of LOOP ? Smaller Lisp minds want to
|> know.
|
| The first question is whether the loop is to be imperative (passes
| through a series of states having some side-effect) or functional
| (computes a value of some kind).  This is a stylistic question;
| functional iteration can always be done imperatively, but is often
| clearer when expressed functionally.

| So, for imperative loops where the iterations are in one-to-one
| correspondence with the members of a specific collection, I use DOLIST
| or (with FSet) DO-SET, DO-SEQ, or DO-MAP.  In more complex situations,
| where the iterations are not in one-to-one correspondence with any set
| known in advance, I will use one of DO (yes I really use good old DO),

I don't think there is any "style" distinction between DO/DO* and
extended LOOP --- it's just a matter of catering to base tastes. (Yes I
think a `fine distinction' is helpful here :)

[...]

| For functional iteration there are really three sets of important
| functions.  The Common Lisp builtins are MAPCAR, REDUCE, and
| REMOVE-IF- NOT.

Note CL already implements a subtle plan in encouraging functional
iteration with generic sequences by not providing the equivalent loop
keywords.  My conspiracy sensors say this may have been be an oversight.
If your code should deal with all cl:sequences you would automatically
prefer


	(MAP nil (lambda (X) ...) SEQUENCE)

over

        (DOLIST) or (LOOP FOR x IN list) or (LOOP FOR x ACROSS vector)


| I've mentioned GMAP here once or twice.  I'm quite fond of it, but
| I've never been able to interest anyone else in using it, AFAIK.  It's
| somewhat like Waters' Series package, but far simpler in both concept
| and implementation.  Nevertheless, in my experience, it handles a lot
| of cases very elegantly.
|
| All GMAP does is generalize CL:MAP in two ways: first by providing an
| extensible set of result constructors, and secondly by providing an
| extensible set of argument generators.  So where CL:MAP can only
| generate arguments to the mapped function by iterating over sequences,
| and can only produce some sequence type as its result, GMAP (being a
| macro) has syntax that lets you specify how to generate each argument,
| and also how to collect up the results (so it combines the
| functionality of MAP and REDUCE).
|
| You can find GMAP and FSet, respectively, at:
|
| http://common-lisp.net/project/misc-extensions/
| http://common-lisp.net/project/fset/

--
Madhu
From: Scott Burson
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <f6d4118d-b079-4853-bcd6-77ffa8659a73@d7g2000prl.googlegroups.com>
On Apr 28, 2:53 am, chthon <··············@pandora.be> wrote:
>
> What do you use then instead ofLOOP? Smaller Lisp minds want to
> know.

Arrgh -- I wrote a long reply to this yesterday, but Google evidently
dropped it on the floor.  Crap!

I will try again, but probably not until this weekend.

-- Scott
From: Marco Antoniotti
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <27fe98a7-61fe-4ef5-90e2-cbae65daffdb@q16g2000yqg.googlegroups.com>
On Apr 24, 2:56 pm, Kenneth Tilton <·········@gmail.com> wrote:
> Lisp G*ds Only, for reasons obvious:
>
> What is/are the big chunks of CL you have never used? Series does not count.
>
> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
>
> So my survey response:
>
>    restarts
>
> btw, Anybody else doing interactive utility software with nothing more
> than restarts?

I have used everything sooner or later.  And there are many things I
would like to use but that are not completely standardized (e.g.,
MOP).  As an example, I was dubious about symbol macros.  Then I found
out why they are there.  Some things are so useful that I
reimplemented them in other languages.  Notably the pretty printer.  I
even dabbled in method combinations to play around with AOP.

Cheers
--
Marco
From: Lars Rune Nøstdal
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <e88cb089-114b-4000-9a65-4ec78c96bde4@m19g2000yqk.googlegroups.com>
On Apr 24, 2:56 pm, Kenneth Tilton <·········@gmail.com> wrote:
>
> What is/are the big chunks of CL you have never used? Series does not count.

Readtable stuff.
From: Mark Tarver
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <0c5d4158-bd7c-4f43-a0a7-f6219a39171f@q9g2000yqc.googlegroups.com>
On 24 Apr, 13:56, Kenneth Tilton <·········@gmail.com> wrote:
> Lisp G*ds Only, for reasons obvious:
>
> What is/are the big chunks of CL you have never used? Series does not count.
>
> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
>
> So my survey resI tend to learn CL on demand and don't count myself as a guru.  Probably its easier to characterise what I do use and then do the subtraction.

Stuff I do use regularly
================

The basic pure functional subset of the early era very intensively

I/O

FORMAT a lot though probably not the full regalia of options.
Read/write from/to files
set is about the only destructive operation I use.

Stuff I have used very occasionally
=========================

But inside Qi (I don't actually program in Qi using these things)

hash-table lookups
progv
conditions (slightly)
features (sigh; wish CL was more specified sometimes)
blocks, return and jumps for encoding Prolog cuts and optimising
pattern-matching
readtable

And no CLOS, RPLACA, bit twiddling, LOOP, DO etc.

Mark
From: Didier Verna
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <muxhc0cq3um.fsf@uzeb.lrde.epita.fr>
Stuff I never use: eval
Stuff nobody uses but me: nreconc

-- 
European Lisp Symposium, May 2009: http://www.european-lisp-symposium.org
European Lisp Workshop, July 2009: http://elw.bknr.net/2009

Scientific site:   http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com
From: Rob Warnock
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <btCdnZp_ebE8Vm7UnZ2dnUVZ_vidnZ2d@speakeasy.net>
Didier Verna  <······@lrde.epita.fr> wrote:
+---------------
| Stuff I never use: eval
| Stuff nobody uses but me: nreconc
+---------------

Stuff I never used before 'cuz I never noticed them 'til now
(thanks, Didier!):

    REVAPPEND
    NRECONC

Stuff I know about but almost never use (not sure why):

    ELT (dunno why, maybe learned AREF & NTH first?)
    MAP-INTO
    MERGE
    SUBLIS/NSUBLIS
    BUTLAST/NBUTLAST
    LDIFF/TAILP
    Any of the explicit PPRINT-* functions (except as invoked
      indirectly via FORMAT directives)
    SCHAR
    REMHASH/CLRHASH/SXHASH
    WITH-HASH-TABLE-ITERATOR (tend to use LOOP forms instead)
    Logical pathnames (too Unix-centric, I guess)
    TARCE/UNTRACE/STEP
    Other than simple bits of CLOS (but do use method dispatch on STRUCTUREs)
    SYMBOL-PLIST
    COMPLEX numbers (just haven't had the need yet)
    BIT vectors (but I do *lots* of bit-banging on integers!!)

Stuff I use a lot and consider underappreciated [especially by
those who think that the regexp hammer fits all "nails"]:

    MISMATCH
    SEARCH (esp. as weird-but-useful :TEST arg to other sequence funcs)
    POSITION-IF

Stuff I use occasionally in "unusual"(?) ways:

    TREE-EQUAL (to walk *one* tree! ["tree1" == "tree2", with :TEST arg])
    NSUBST/NSUBST-IF (ditto)


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: ··········@gmail.com
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <41dac0fc-93e7-4635-8783-5bb27bb1eefd@t36g2000prt.googlegroups.com>
On 25 abr, 23:49, ····@rpw3.org (Rob Warnock) wrote:
> Didier Verna  <······@lrde.epita.fr> wrote:
> +---------------
> | Stuff I never use: eval
> | Stuff nobody uses but me: nreconc
> +---------------
>
> Stuff I never used before 'cuz I never noticed them 'til now
> (thanks, Didier!):
>
>     REVAPPEND
>     NRECONC

Hum... I didn't know these either, though I am not a G*d Lisper. If I
ever needed this function I would probably use reverse followed by
append instead, so I understand why no one knows about it.
>
> Stuff I know about but almost never use (not sure why):
>
>     ELT (dunno why, maybe learned AREF & NTH first?)
>     MAP-INTO
>     MERGE
>     SUBLIS/NSUBLIS
>     BUTLAST/NBUTLAST
>     LDIFF/TAILP
>     Any of the explicit PPRINT-* functions (except as invoked
>       indirectly via FORMAT directives)
>     SCHAR
>     REMHASH/CLRHASH/SXHASH
>     WITH-HASH-TABLE-ITERATOR (tend to use LOOP forms instead)
>     Logical pathnames (too Unix-centric, I guess)
>     TARCE/UNTRACE/STEP
>     Other than simple bits of CLOS (but do use method dispatch on STRUCTUREs)
>     SYMBOL-PLIST
>     COMPLEX numbers (just haven't had the need yet)
>     BIT vectors (but I do *lots* of bit-banging on integers!!)
>
> Stuff I use a lot and consider underappreciated [especially by
> those who think that the regexp hammer fits all "nails"]:
>
>     MISMATCH
>     SEARCH (esp. as weird-but-useful :TEST arg to other sequence funcs)
>     POSITION-IF
>
> Stuff I use occasionally in "unusual"(?) ways:
>
>     TREE-EQUAL (to walk *one* tree! ["tree1" == "tree2", with :TEST arg])
>     NSUBST/NSUBST-IF (ditto)
>
> -Rob
>
> -----
> Rob Warnock                     <····@rpw3.org>
> 627 26th Avenue                 <URL:http://rpw3.org/>
> San Mateo, CA 94403             (650)572-2607

If I would mention everything I never used, I would need to see the
hyperspec. There are so many functions, I never used at least a third
of it.
From: Kenneth Tilton
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <49f3f2bb$0$25617$607ed4bc@cv.net>
··········@gmail.com wrote:
> On 25 abr, 23:49, ····@rpw3.org (Rob Warnock) wrote:
>> Didier Verna  <······@lrde.epita.fr> wrote:
>> +---------------
>> | Stuff I never use: eval
>> | Stuff nobody uses but me: nreconc
>> +---------------
>>
>> Stuff I never used before 'cuz I never noticed them 'til now
>> (thanks, Didier!):
>>
>>     REVAPPEND
>>     NRECONC
> 
> Hum... I didn't know these either, though I am not a G*d Lisper. If I
> ever needed this function I would probably use reverse followed by
> append instead, so I understand why no one knows about it.
>> Stuff I know about but almost never use (not sure why):
>>
>>     ELT (dunno why, maybe learned AREF & NTH first?)
>>     MAP-INTO
>>     MERGE
>>     SUBLIS/NSUBLIS
>>     BUTLAST/NBUTLAST
>>     LDIFF/TAILP
>>     Any of the explicit PPRINT-* functions (except as invoked
>>       indirectly via FORMAT directives)
>>     SCHAR
>>     REMHASH/CLRHASH/SXHASH
>>     WITH-HASH-TABLE-ITERATOR (tend to use LOOP forms instead)
>>     Logical pathnames (too Unix-centric, I guess)
>>     TARCE/UNTRACE/STEP
>>     Other than simple bits of CLOS (but do use method dispatch on STRUCTUREs)
>>     SYMBOL-PLIST
>>     COMPLEX numbers (just haven't had the need yet)
>>     BIT vectors (but I do *lots* of bit-banging on integers!!)
>>
>> Stuff I use a lot and consider underappreciated [especially by
>> those who think that the regexp hammer fits all "nails"]:
>>
>>     MISMATCH
>>     SEARCH (esp. as weird-but-useful :TEST arg to other sequence funcs)
>>     POSITION-IF
>>
>> Stuff I use occasionally in "unusual"(?) ways:
>>
>>     TREE-EQUAL (to walk *one* tree! ["tree1" == "tree2", with :TEST arg])
>>     NSUBST/NSUBST-IF (ditto)
>>
>> -Rob
>>
>> -----
>> Rob Warnock                     <····@rpw3.org>
>> 627 26th Avenue                 <URL:http://rpw3.org/>
>> San Mateo, CA 94403             (650)572-2607
> 
> If I would mention everything I never used, I would need to see the
> hyperspec. There are so many functions, I never used at least a third
> of it.

Not to deprecate more detailed offerings for they too serve by opening 
eyes, but the survey is looking for undiscovered continents, not street 
addresses. Big stuff like blackbelt format, loop, conditions, MOP, 
pprint, restarts. symbol macros and tagbody feel continenty even though 
they are atomic.

kzo
From: Pascal Costanza
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <75od3oF19djaaU2@mid.individual.net>
Didier Verna wrote:
> Stuff I never use: eval
> Stuff nobody uses but me: nreconc

Not true, I also use nreconc. ;)


Pascal

-- 
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal J. Bourguignon
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <7cab60c2nj.fsf@pbourguignon.anevia.com>
Pascal Costanza <··@p-cos.net> writes:

> Didier Verna wrote:
>> Stuff I never use: eval
>> Stuff nobody uses but me: nreconc
>
> Not true, I also use nreconc. ;)

I've used it more than once, and REVAPPEND too.

If they weren't so useful, they wouldn't have made it into the standard ;-)
-- 
__Pascal Bourguignon__
From: Thomas F. Burdick
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <1c8b9464-2d46-43b9-ae95-2e5dded92346@x29g2000prf.googlegroups.com>
On Apr 24, 2:56 pm, Kenneth Tilton <·········@gmail.com> wrote:
> Lisp G*ds Only, for reasons obvious:
>
> What is/are the big chunks of CL you have never used? Series does not count.

I've only made very light use of the pretty printer, and all the
tabulated-output stuff in FORMAT I've never touched. Also, the CLtL2
environments stuff along with Franz's modern reworking of it.

> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.
>
> So my survey response:
>
>    restarts
>
> btw, Anybody else doing interactive utility software with nothing more
> than restarts?

Yeah, sometimes. I was motivated to learn about them the first time I
wanted to add an option to the restart list when presented with the
MCL debugger. Nowadays I see a lot of Ltk buttons that behind the
scenes just select a restart.
From: kevinlivingston
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <4e7a653f-edc4-42cf-8ae3-aaef1ff8576c@w31g2000prd.googlegroups.com>
On Apr 24, 7:56 am, Kenneth Tilton <·········@gmail.com> wrote:
> What is/are the big chunks of CL you have never used? Series does not count.

Some of the big things that CL waves around that I don't use much are
bignums, and really I don't call EVAL that much (FUNCALL and APPLY all
the time, of course).  And yeah, I don't use restarts that much
(ever?) programming, debugging they come up all the time though!
Speaking of debugging I don't really use STEP, since we have TRACE.  I
rarely use LOOP, and if I have used method combination it was only
once.

If you are looking for candidates for least necessary function, I
think I have only called Y-OR-N-P just to prove to myself it was
actually in there.  But I tend to do most of my interaction with lisp
through web pages, or analyzing data in the REPL or dumping it to
files to load and plot in R.


> Motivation: my standard retort to Lisp is too big is that I use it all,
> then I started thinking about using restarts to make an interactive
> developer utility and realized it was Back to School time.


While I don't use all of it all of the time I do seem to use quite a
bit, and it's nice to have learned one language that has most of what
I need most of the time.  I think a more interesting "survey question"
would be what do you find yourself reimplementing over and over that's
not already in there?

For me I don't use arrays and vectors that much, but a nice queue
would be helpful.  And I constantly bring in my map all files in a
directory code.  (Surprisingly map-plist doesn't exist either.)
Because of the kind of work I do, unification and memoization seem to
come up everywhere too.

Kevin
From: Rob Warnock
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <utqdnd_Yy6Pd7WvUnZ2dnUVZ_jCdnZ2d@speakeasy.net>
kevinlivingston  <···············@gmail.com> wrote:
+---------------
| While I don't use all of it all of the time I do seem to use quite a
| bit, and it's nice to have learned one language that has most of what
| I need most of the time.
+---------------

Yes, indeed!

+---------------
| I think a more interesting "survey question" would be what do you find
| yourself reimplementing over and over that's not already in there?
+---------------

My standard utilities package:

(defpackage :org.rpw3.utils
  (:nicknames :utils)
  (:use :cl :ext)
  (:export
   ;; Readmacros:
   #:set-sharp-bang-reader	; Enable #! as a comment (for shell scripts).
   #:set-sharp-dollar-reader	; Experimental LAMBDA abbreviation [c.f. FN].
   #:set-zero-x-reader		; C-style hex numbers, e.g. 0x1234. [BUGGY!]

   ;; Macros:
   #:deflex			; "Global lexical variables" (sort of).
   #:fn				; Alias for LAMBDA.
   #:dbgv			; Debug printing of forms & values.
   #:dbgvht			; Same, but outputs as HTML.
   #:with-output-to-file	; Save typing in the most common output case.

   ;; String-hacking functions:
   #:getenv			; Portable version.
   #:strcat			; Syntactic sugar [with a compiler macro, too].
   #:join-strings		; STRCAT with infix separators.
   #:join-strings/sql-quoted	; JOIN-STRINGS with SQL-quoting of some chars.
   #:stringify			; Coerce items in atom/list/tree to strings.
   #:file-string		; Suck up a whole file into a string.
   #:file-lines			;   ...into a list of strings (lines).
   #:file-forms			;   ...into a list of forms (s-exprs).
   #:stream-string		; Same as above, but for an open stream
   #:stream-lines
   #:stream-forms
   #:\0x			; A FORMAT printer for hex, e.g. "~2/0x/".

   ;; Time-formatters [see also CMUCL's EXT:FORMAT-UNIVERSAL-TIME]:
   #:format-time-ctime
   #:format-time-iso8601

   ;; Misc. other
   #:iota			; (count &optional (start 0) (step 1))
   #:mean
   #:median
   #:std-dev

   ;; CMUCL MP convenience functions for servers that leave a REPL running:
   #:ensure-idle-process-running ; Initial REPL -> idle proc; new proc -> REPL.
   #:restart-top-level		; If accidentally kill REPL proc.
   #:break-top-level		; Recover from certain tricky typos.
   ))

And some support for web hacking:

(defpackage :org.rpw3.cgi.uri
  (:nicknames :uri)
  (:use :cl :ext :htout :utils)
  (:export
    ;; Functions
    #:read/parse-http-request
    #:query-string-alist
    #:cgi-lookup
    #:cgi-lookup-all
    #:request-env
    #:request-binding
    #:split-path
    #:extract/trim-bindings
    #:match-query/bindings
    #:match-assoc
    #:build-continuation
    #:decode-hex
    #:url-decode
    #:register-uri-handler
    #:find-uri-handler
    #:not-found-page
    #:forbidden-page
    #:fallback-page
    #:internal-error-page
    #:list-html-table

    ;; Structures
    #:http-request
    #:http-server
    #:uri-handler
    ...[and friends]...

    ...[other misc.]...
    ))


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Mark Wooding
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <871vrdnk56.fsf.mdw@metalzone.distorted.org.uk>
····@rpw3.org (Rob Warnock) writes:

> kevinlivingston  <···············@gmail.com> wrote:
> +---------------
> | I think a more interesting "survey question" would be what do you find
> | yourself reimplementing over and over that's not already in there?
> +---------------

Yes, indeed.

I think the function I find myself typing in most frequently is

        (defun listify (thing)
          (if (listp thing)
              thing
              (list thing)))

I also get a lot of use out of this hack:

        (defun whitespace-char-p (ch)
          (case ch
            (#.(loop for i below char-code-limit
                     for ch = (code-char i)
                     unless (with-input-from-string (in (string ch))
                              (peek-char t in nil))
                     collect ch)
               t)
            (t nil)))

And the usual WITH-GENSYMS and LET*/GENSYMS (an inadvertent rewrite of
ONCE-ONLY).

>    #:with-output-to-file	; Save typing in the most common output case.

I have a SAFELY-WRITING macro which opens a stream onto a fresh file
(using :IF-EXISTS NIL), and either renames the file into place on
successful completion or deletes it on failure.  It's based on a more
complicated infrastructure of stuff which handles multiple files and
other operations such as file deletion.

>    #:stringify		; Coerce items in atom/list/tree to strings.

I have a function with this name, but it's simpler:

        (defun stringify (thing)
          (typecase thing
            (string thing)
            (symbol (symbol-name thing))
            (t (princ-to-string thing))))

-- [mdw]
From: Rob Warnock
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <mtidnRf99qcdcWvUnZ2dnUVZ_vCdnZ2d@speakeasy.net>
Mark Wooding  <···@distorted.org.uk> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) writes:
| >    #:with-output-to-file	; Save typing in the most common output case.
| 
| I have a SAFELY-WRITING macro which opens a stream onto a fresh file
| (using :IF-EXISTS NIL), and either renames the file into place on
| successful completion or deletes it on failure.  It's based on a more
| complicated infrastructure of stuff which handles multiple files and
| other operations such as file deletion.
+---------------

Mine does the opposite extreme of "safety": it unconditionally
writes over the file whether or not it exists [unless you supply
a different explicit :IF-EXISTS]:

(defmacro with-output-to-file ((stream filename
                                &key (direction :output) (if-exists :supersede)
                                &rest rest &allow-other-keys)
                               &body body)
  `(with-open-file (,stream ,filename
                    :direction ,direction :if-exists ,if-exists ,@rest)
    ,@body))

+---------------
| >    #:stringify		; Coerce items in atom/list/tree to strings.
| 
| I have a function with this name, but it's simpler:
|         (defun stringify (thing)
|           (typecase thing
|             (string thing)
|             (symbol (symbol-name thing))
|             (t (princ-to-string thing))))
+---------------

Mine translates NIL to "", rather than "NIL", mainly because
of what I tend to use it for [building web pages & other docs].


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Madhu
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <m3ws952evt.fsf@moon.robolove.meer.net>
* (Rob Warnock) <································@speakeasy.net> :
Wrote on Mon, 27 Apr 2009 21:56:00 -0500:

| kevinlivingston  <···············@gmail.com> wrote:
| +---------------
| | While I don't use all of it all of the time I do seem to use quite a
| | bit, and it's nice to have learned one language that has most of what
| | I need most of the time.
| +---------------

From my .cmucl-init.lisp, which incidentally works across allegro and
lispworks too, here is a selection of some 45/266 '^(def.*' lines. 

Most of it should  be familiar to all of you. :)



function compose (&rest functions)	; composes functions as if by m-v-c
function group2 (list &key (test #'eql) (key #'identity))     ·············@registered.motzarella.org

function nshuffle (seq &aux (len (length seq)))
function mapsome (predicate list &rest more-lists)
function delete-nth (list position)
function plist-sans-keys (plist &rest keys) ; <················@naggum.no>
function popmax (list &optional (cmp #'>) &key key)
function insert-ordered (item list &optional (predicate #'<) &key key test test-not)
macro pushnew-ordered (obj place predicate &rest keys &environment env)

function ordered-intersection (list1 list2 predicate)
function suffixp (suffix sequence &key (test #'equalp) &aux idx)
function prefixp (prefix sequence &key (test #'equalp) &aux idx)

function flatten (x &aux stack result)
function tree-depth (tree &aux (global-depth 0) stack) ; madhu 061123
function position-ordered (elem array &optional (predicate #'<) &key (test #'eql) (start 0) end)
function round-to-accuracy (value digits-after-decimal-point)

macro case-equal (which &body clauses)
macro ecase-equal (which &body clauses)
macro continuing-from-errors ((&rest condition-types) &body body)

function substr (string &optional (start 0) end)
function string-split (char-bag string &key (start 0) end (collect-empty t))
function $tring-reader (stream $ arg)	; doesnt escape backslash


function copy-buffered-io (input output &key (block-size 4096) element-type buffer)
function slurp-file (pathname &optional buffer &key element-type)
function slurp-stream (stream &optional buffer &key element-type chunk-size)
function string->file (string filename)
function stream->file (stream filename &key element-type buffer-size buffer)
function read-lines-from-stream (stream &optional lines-array start end &key hint)
function write-lines-to-stream (lines-array &optional stream start end)
function slurp-lines (pathname &optional (start 0) end &key lines-array)
function dump-lines (lines-array pathname &optional (start 0) end)

macro with-decompressed-stream (stream compressed-file-pathname ..)
macro with-flames-to-devnull (&body body)

macro undefmethod (function-name &rest args)
macro choose-with-restarts-internal (choices &body body)

function package-add-nicknames (pkg &rest nicknames)
function package-remove-nicknames (pkg &rest nicknames)
function clean-syms (pkg)
macro with-slots-in-package ((&rest slot-vars) obj pkg &body body)
function hashtable->alist
function  hashtable->plist

function lc (pathname &key library-p binary-directory ;; compile and load
	dry-run force source-directory source-file-types
	create-directories)
function pwd ()
function cd ()
function ps ()
function delete-directory (path)
macro in-directory (directory &body forms)
function symbolic-link-p (pathname &optional (stats (stat2 pathname)))
function directory-p (pathname &optional (stats (stat2 pathname)))
function regular-file-p (pathname &optional (stats (stat2 pathname)))
function iso-8601-date (&key stream utime tzsuppress-time-p suppress-tz-p)
macro with-file-dates-preserved ((pathname) &body body)
function probe-directory (p)
function dired (path &optional f (depth 0) maxdepth &aux p) ; `unix find'

function wildify (root &rest components) ;; make a **;*.*.* logical pathname
macro with-open-pipe ((stream command &key (shell-type "/bin/sh")) &body body)

--
Madhu
From: Madhu
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <m3tz492eqn.fsf@moon.robolove.meer.net>
* (Rob Warnock) <································@speakeasy.net> :
Wrote on Mon, 27 Apr 2009 21:56:00 -0500:
| +---------------
| | I think a more interesting "survey question" would be what do you find
| | yourself reimplementing over and over that's not already in there?
| +---------------
|
| My standard utilities package:

From my .cmucl-init.lisp, which incidentally works across allegro and
lispworks too, here is a selection of some 45/266 '^(def.*' lines.

Most of it should  be familiar to all of you. :)


function compose (&rest functions)        ; composes functions as if by m-v-c
function group2 (list &key (test #'eql) (key #'identity))     ·············@registered.motzarella.org

function nshuffle (seq &aux (len (length seq)))
function mapsome (predicate list &rest more-lists)
function delete-nth (list position)
function plist-sans-keys (plist &rest keys) ; <················@naggum.no>
function popmax (list &optional (cmp #'>) &key key)
function insert-ordered (item list &optional (predicate #'<) &key key test test-not)
macro pushnew-ordered (obj place predicate &rest keys &environment env)

function ordered-intersection (list1 list2 predicate)
function suffixp (suffix sequence &key (test #'equalp) &aux idx)
function prefixp (prefix sequence &key (test #'equalp) &aux idx)

function flatten (x &aux stack result)
function tree-depth (tree &aux (global-depth 0) stack) ; madhu 061123
function position-ordered (elem array &optional (predicate #'<) &key (test #'eql) (start 0) end)
function round-to-accuracy (value digits-after-decimal-point)

macro case-equal (which &body clauses)
macro ecase-equal (which &body clauses)
macro continuing-from-errors ((&rest condition-types) &body body)

function substr (string &optional (start 0) end)
function string-split (char-bag string &key (start 0) end (collect-empty t))
function $tring-reader (stream $ arg)	; doesnt escape backslash


function copy-buffered-io (input output &key (block-size 4096) element-type buffer)
function slurp-file (pathname &optional buffer &key element-type)
function slurp-stream (stream &optional buffer &key element-type chunk-size)
function string->file (string filename)
function stream->file (stream filename &key element-type buffer-size buffer)
function read-lines-from-stream (stream &optional lines-array start end &key hint)
function write-lines-to-stream (lines-array &optional stream start end)
function slurp-lines (pathname &optional (start 0) end &key lines-array)
function dump-lines (lines-array pathname &optional (start 0) end)

macro with-decompressed-stream (stream compressed-file-pathname ..)
macro with-flames-to-devnull (&body body)

macro undefmethod (function-name &rest args)
macro choose-with-restarts-internal (choices &body body)

function package-add-nicknames (pkg &rest nicknames)
function package-remove-nicknames (pkg &rest nicknames)
function clean-syms (pkg)
macro with-slots-in-package ((&rest slot-vars) obj pkg &body body)
function hashtable->alist
function  hashtable->plist

function lc (pathname &key library-p binary-directory ;; compile and load
	dry-run force source-directory source-file-types
	create-directories)
function pwd ()
function cd ()
function ps ()
function delete-directory (path)
macro in-directory (directory &body forms)
function symbolic-link-p (pathname &optional (stats (stat2 pathname)))
function directory-p (pathname &optional (stats (stat2 pathname)))
function regular-file-p (pathname &optional (stats (stat2 pathname)))
function iso-8601-date (&key stream utime tzsuppress-time-p suppress-tz-p)
macro with-file-dates-preserved ((pathname) &body body)
function probe-directory (p)
function dired (path &optional f (depth 0) maxdepth &aux p) ; `unix find'

function wildify (root &rest components) ;; make a **;*.*.* logical pathname
macro with-open-pipe ((stream command &key (shell-type "/bin/sh")) &body body)

--
Madhu
From: John Thingstad
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <op.us3hv1q1ut4oq5@pandora>
På Tue, 28 Apr 2009 13:34:56 +0200, skrev Madhu <·······@meer.net>:

>
> * (Rob Warnock) <································@speakeasy.net> :
> Wrote on Mon, 27 Apr 2009 21:56:00 -0500:
> | +---------------
> | | I think a more interesting "survey question" would be what do you  
> find
> | | yourself reimplementing over and over that's not already in there?
> | +---------------
> |
> | My standard utilities package:
>
> From my .cmucl-init.lisp, which incidentally works across allegro and
> lispworks too, here is a selection of some 45/266 '^(def.*' lines.
>
> Most of it should  be familiar to all of you. :)
>

 From the look of it you should study the , directive of SLIME.
, l - load asdf library
, cd - change directory
, pwd - print working directory and so on.

a lot of that stuff is already done..

-----------------------
John Thingstad
From: Madhu
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <m3prex2c83.fsf@moon.robolove.meer.net>
* "John Thingstad" <·················@pandora> :
Wrote on Tue, 28 Apr 2009 13:51:27 +0200:

| On Tue, 28 Apr 2009 13:34:56 +0200, skrev Madhu <·······@meer.net>:
|> * (Rob Warnock) <································@speakeasy.net> :
|> Wrote on Mon, 27 Apr 2009 21:56:00 -0500:
|> | +---------------
|> | | I think a more interesting "survey question" would be what do you
|> | | find yourself reimplementing over and over that's not already in
|> | | there?
|> | +---------------
|> | My standard utilities package:
|> From my .cmucl-init.lisp, which incidentally works across allegro and
|> lispworks too, here is a selection of some 45/266 '^(def.*' lines.
|>
|> Most of it should  be familiar to all of you. :)
|
| From the look of it you should study the , directive of SLIME.
| a lot of that stuff is already done..

Well, I wrote this stuff before SLIME existed.  At that time only CLOCC
was available, but it was someone else's init file anyway :)

[More precisely I started writing it before SLIME existed... I'm still
writing it. Like the .emacs, the perfect init file is a lifelong task]

Also I don't use SLIME exclusively and need the convenience commands
most on barebores REPs.

--
Madhu
From: Pillsy
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <61c2705f-98fa-493b-8e5b-3904cfe444a7@s38g2000prg.googlegroups.com>
On Apr 27, 5:52 am, kevinlivingston <···············@gmail.com> wrote:
> I think a more interesting "survey question"
> would be what do you find yourself reimplementing over and over that's
> not already in there?

Here are some selected chunks of my utilities package.

(defun row-major-subscripts (array rmi)
  "Returns the list of subscripts associated with the row-major-index
RMI in array ARRAY, so that
  \(row-major-aref array rmi) = (apply #'aref array rmi)"
  (let ((dims (reverse (array-dimensions array)))
	(subs '()))
    (labels ((collect-sub (rmi)
	       (if (null dims)
		   subs
		   (multiple-value-bind (remains index)
		       (floor rmi (pop dims))
		     (push index subs)
		     (collect-sub remains)))))
      (collect-sub rmi))))

(defun hash-table->alist (hash-table)
  (let ((alist '()))
    (maphash (lambda (k v)
	       (push (cons k v) alist))
	     hash-table)
    alist))

(defun class-name-of (object)
  "Returns the symbol that names the class of OBJECT."
  (class-name (class-of object)))

(defun lambda-list-keyword-p (x)
  "Checks to see whether X is a lambda list keyword."
  (member x '(&rest &aux &key &optional &allow-other-keys)))

(defun zip (&rest more-lists)
  (apply #'mapcan #'list more-lists))

(defun riffle (list thing)
  (and (not (null list))
       (cons (first list)
	     (loop
		:for elt :in (rest list)
		:collect thing
		:collect elt))))

Cheers,
Pillsy
From: szergling
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <6183c941-44ac-4afb-8291-166864f8e6e5@u9g2000pre.googlegroups.com>
On Apr 29, 10:51 am, Pillsy <·········@gmail.com> wrote:

> (defun zip (&rest more-lists)
>   (apply #'mapcan #'list more-lists))
>

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

This actually looks like a real zipper!
Doesn't zip usually refer to this (eg Python)?

CL-USER> (defun zip (&rest lists)
           (apply #'mapcar #'list lists))
ZIP
CL-USER> (zip '(1 2 3) '(4 5 6))
((1 4) (2 5) (3 6))
CL-USER>
From: szergling
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <89038ddd-3d0b-4b12-a3de-a8dd6b51979e@k19g2000prh.googlegroups.com>
On Apr 29, 10:51 am, Pillsy <·········@gmail.com> wrote:

> (defun zip (&rest more-lists)
>   (apply #'mapcan #'list more-lists))
>

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

This actually looks like a real zipper!
Doesn't zip usually refer to this (eg Python)?

CL-USER> (defun zip (&rest lists)
           (apply #'mapcar #'list lists))
ZIP
CL-USER> (zip '(1 2 3) '(4 5 6))
((1 4) (2 5) (3 6))
CL-USER>
From: Rob Warnock
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <bJWdnQ1HF8YkZmXUnZ2dnUVZ_hOdnZ2d@speakeasy.net>
szergling  <···············@gmail.com> wrote:
+---------------
| Pillsy <·········@gmail.com> wrote:
| > (defun zip (&rest more-lists)
| >   (apply #'mapcan #'list more-lists))
| 
| CL-USER> (zip '(1 2 3) '(4 5 6))
| (1 4 2 5 3 6)
| 
| This actually looks like a real zipper!
| Doesn't zip usually refer to this (eg Python)?
| 
| CL-USER> (defun zip (&rest lists)
|            (apply #'mapcar #'list lists))
| ZIP
| CL-USER> (zip '(1 2 3) '(4 5 6))
| ((1 4) (2 5) (3 6))
| CL-USER>
+---------------

To bring us back to obscure features of CL... Note that CL
already has a function with semantics similar to the latter:

    > (pairlis '(1 2 3) '(4 5 6))

    ((3 . 6) (2 . 5) (1 . 4))
    > (pairlis '(1 2 3) '(4 5 6) '((x . y) (z . w)))

    ((3 . 6) (2 . 5) (1 . 4) (X . Y) (Z . W))
    > 

And while we're in that part of town, don't forget ACONS:

    > (acons 1 4
	(acons 2 5
	  (acons 3 6 nil)))

    ((1 . 4) (2 . 5) (3 . 6))
    > 


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pillsy
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <d5df4a84-1891-42d7-b956-bdf60919f91e@f1g2000prb.googlegroups.com>
On Apr 29, 6:06 pm, szergling <···············@gmail.com> wrote:
> On Apr 29, 10:51 am, Pillsy <·········@gmail.com> wrote:

> > (defun zip (&rest more-lists)
> >   (apply #'mapcan #'list more-lists))

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

> This actually looks like a real zipper!
> Doesn't zip usually refer to this (eg Python)?

> CL-USER> (defun zip (&rest lists)
>            (apply #'mapcar #'list lists))
> ZIP

Hah. I'd never actually used the function in another language, just
heard it described. :)

I think my ZIP is more useful, though of course I'll have to find a
new name. Maybe I'll call that one RIFFLE and rename the old RIFFLE to
something else....

Cheers,
Pillsy
From: Thierry Pirot
Subject: Re: zip (was : It's A Big Language Survey)
Date: 
Message-ID: <83ab5aqrfw.fsf_-_@thierrypirot.net>
szergling writes:
> On Apr 29, 10:51 am, Pillsy <·········@gmail.com> wrote:
> > (defun zip (&rest more-lists)
> >   (apply #'mapcan #'list more-lists))
> 
> CL-USER> (zip '(1 2 3) '(4 5 6))
> (1 4 2 5 3 6)
> 
> This actually looks like a real zipper!
> Doesn't zip usually refer to this (eg Python)?
> 
> CL-USER> (defun zip (&rest lists)
>            (apply #'mapcar #'list lists))
> 
> CL-USER> (zip '(1 2 3) '(4 5 6))
> ((1 4) (2 5) (3 6))
>
Then use MAPCAN instead of MAPCAR.  
From: Kaz Kylheku
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <20090508231509.542@gmail.com>
On 2009-04-27, kevinlivingston <···············@gmail.com> wrote:
> While I don't use all of it all of the time I do seem to use quite a
> bit, and it's nice to have learned one language that has most of what
> I need most of the time.  I think a more interesting "survey question"
> would be what do you find yourself reimplementing over and over that's
> not already in there?

If you're implementing it over and over again, maybe it's hard to pin down
the requirements.

But what have you implemented once and then successfully reused many times?

> For me I don't use arrays and vectors that much, but a nice queue
> would be helpful.

A deque in Common Lisp can be made without encapsulation. Simply take two
assignable locations which hold lists, and treat them as the opposite
outward-facing ends of the dequeue. One of them holds the head piece, the other
the tail piece. Adding to the head or tail is therefore done using the standard
PUSH macro, using one location or the other. All you need is a funky pop
macro which can remove an element from either end.  It takes both locations
as arguments. To pop from the opposite end, reverse the arguments.

http://paste.lisp.org/display/71592

There there are two implementations; a naive simple one, and an optimized one.
Even though popping involves reversing a list, the amortized cost of the
operations is O(1). I.e. pushing a large number N of items into one end and
popping them out the other is O(N). (This is true of the simple implementation
too, but the simple implementation is susceptible to ``silly flip'' behavior,
when confronted with certain obvious patterns of use, which inflate the
complexity.)
From: Kaz Kylheku
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <20090509030102.417@gmail.com>
On 2009-04-27, kevinlivingston <···············@gmail.com> wrote:
> On Apr 24, 7:56 am, Kenneth Tilton <·········@gmail.com> wrote:
>> What is/are the big chunks of CL you have never used? Series does not count.
>
> Some of the big things that CL waves around that I don't use much are
> bignums

How do you know you don't use bignums? The knee between fixnums and bignums is
implementation-defined. What if it occurs at +/- 255?

If you use exact numbers at all in your CL programs, you benefit from bignums,
because you are free from worrying about annoying corner cases, like ``what if
adding these two numbers overflows 32 bits''?

If you don't have bignums, you have to validate that no overflows happen.

So even if your algorithms don't obviously require bignums, you still have
the safety net there. A safety net is valuable even if nobody falls down.

If you never wrote a program that exhibited a type mismatch, would you say that
you don't ``use'' type checking? :)
From: Brian - qbg
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <770a9ae8-211d-433b-8570-b1f0d33a7963@i28g2000prd.googlegroups.com>
On Apr 28, 3:10 pm, Kaz Kylheku <········@gmail.com> wrote:
> How do you know you don't use bignums? The knee between fixnums and bignums is
> implementation-defined. What if it occurs at +/- 255?
Easy.  Quoting the HyperSpec, "The type fixnum is required to be a
supertype of (signed-byte 16)."
From: Pascal Costanza
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <75odbuF19gm6fU1@mid.individual.net>
Kenneth Tilton wrote:
> Lisp G*ds Only, for reasons obvious:
> 
> What is/are the big chunks of CL you have never used? 

I have never used the numerical tower.

And I have never used fourth, fifth, sixth, seventh, eighth, ninth and 
tenth. That's a pretty big chunk, right? ;)


Pascal

-- 
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: GP lisper
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <slrngvfehb.957.spambait@phoenix.clouddancer.com>
On Tue, 28 Apr 2009 15:07:10 +0200, <··@p-cos.net> wrote:
> Kenneth Tilton wrote:
>> Lisp G*ds Only, for reasons obvious:
>> 
>> What is/are the big chunks of CL you have never used? 
>
> I have never used the numerical tower.

Tower???


-- 
Lisp:  Powering `Impossible Thoughts since 1958
From: Kenneth Tilton
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <49f7e329$0$27777$607ed4bc@cv.net>
GP lisper wrote:
> On Tue, 28 Apr 2009 15:07:10 +0200, <··@p-cos.net> wrote:
>> Kenneth Tilton wrote:
>>> Lisp G*ds Only, for reasons obvious:
>>>
>>> What is/are the big chunks of CL you have never used? 
>> I have never used the numerical tower.
> 
> Tower???

Built in a response to the Tower of Babel, leading to a runaway tower 
race that sapped the economies of orators and mathematicians for ... not 
sure where this is going... ah, yes, Towers of Hanoi.... hang on... OK, 
based on my performance tonight my softball team is renaming itself The 
Faceplants....where was I?
From: Rob Warnock
Subject: Re: It's A Big Language Survey
Date: 
Message-ID: <PJidnaICnYJAh2XUnZ2dnUVZ_j-dnZ2d@speakeasy.net>
GP lisper  <········@clouddancer.com> wrote:
+---------------
| <··@p-cos.net> wrote:
| > Kenneth Tilton wrote:
| >> Lisp G*ds Only, for reasons obvious:
| >> What is/are the big chunks of CL you have never used? 
| >
| > I have never used the numerical tower.
| 
| Tower???
+---------------

(*sigh*) Kids these days...  ;-}

    http://en.wikipedia.org/wiki/Numerical_tower
    Numerical tower

    In Scheme and some other Lisp dialects, a numerical tower is the set
    of data types that represent numbers in a given programming language.

    Each type in the tower conceptually "sits on" a more fundamental type,
    so an integer is a rational number and a number, but the inverse
    is not necessarily true, i.e. not every number is an integer; this
    asymmetry implies that a language can allow implicit coercions of
    numerical types - without creating semantic problems - in only one
    direction:  ...

And as usual, CL is more a "ball of mud" than Scheme...  ;-}

The CLHS doesn't use the term "numerical tower" per se, but CL's
numerical tower is implicit in the class precedence lists of its
numeric types [though the "purity" of the class tower is marred
slightly by a few mild restrictions on the COMPLEX and RATIO classes]:

    - t
      - number
	- complex   ; includes #c(real 0.0) but excludes #c(rational 0)
	- real
	  - float
	    - short-float
	    - single-float
	    - double-float
	    - long-float
	  - rational
	    - ratio ; n/d, (and (not (zerop n)) (plusp d) (= (gcd x y) 1))
	    - integer
	      - fixnum
	      - bignum

Also note that while UNSIGNED-BYTE, & SIGNED-BYTE are subtypes of
INTEGER, such values of such types can be in either class FIXNUM
or BIGNUM, so that {UN,}SIGNED-BYTE are *not* "classes" per se,
and thus are not in any of the numeric class precedence lists.
[The CLHS uses a list of Supertypes for these, instead.] Which
also means that, contrary to what one might otherwise expect, BIT,
as a subtype of UNSIGNED-BYTE, is not a sub-*class* of FIXNUM.
That is, while CL's numeric *classes* are a tree, its numeric
*types* are a DAG.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607