From: ··········@bbs.ee.ncu.edu.tw
Subject: The way to access the slots of the class STRING
Date: 
Message-ID: <1131939011.618476.137020@g49g2000cwa.googlegroups.com>
I ask this question because I want to write codes to convert string to
list , or
list to string.

Because STRING is a kind of class , it must has it definition ,
something like :
(defclass string (direct-superclass-name*)
  (slot-specifier*))
and I guess one of the slot-specifiers is TYPE (whose value is STRING),
and another
slot-specifiers is LIST (whose value is the sequence of the string).
Thus if I can access the slots of the class STRING, I can convert
string to list by
directly copying the slot value of LIST insides. And I can convert list
to string
by directly copying the list sequence to the slot value of LIST , then
et the TYPE to
STRING.

So , my key problem is the way to access the slots of the class STRING.
Please help me !
Many thanks!!

From: ······@gmail.com
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <1131942832.603154.246240@g44g2000cwa.googlegroups.com>
Maybe this is what you want.

? (coerce "hello world" 'list)
(#\h #\e #\l #\l #\o #\  #\w #\o #\r #\l #\d)
? (coerce '(#\h #\e #\l #\l #\o #\  #\w #\o #\r #\l #\d) 'string)
"hello world"

Justin Dubs
From: ··········@bbs.ee.ncu.edu.tw
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <1131943173.210897.52670@z14g2000cwz.googlegroups.com>
Exactly ,
Thanks a lot!
From: Bruce Butterfield
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <1131986322.739198.37970@g49g2000cwa.googlegroups.com>
I was under the impression that COERCE is a 'big gun' technique much
akin to EVAL which is to be used only when there are no reasonable
alternatives (Graham's  'ANSI Common Lisp' pg. 162). Wouldn't it be
prefereable to write an explicit STRING-TO-LIST? Or is this really the
way to go?
From: John Thingstad
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <op.sz8rafjepqzri1@mjolner.upc.no>
On Mon, 14 Nov 2005 17:38:42 +0100, Bruce Butterfield <·····@open-tek.com>  
wrote:

> I was under the impression that COERCE is a 'big gun' technique much
> akin to EVAL which is to be used only when there are no reasonable
> alternatives (Graham's  'ANSI Common Lisp' pg. 162). Wouldn't it be
> prefereable to write an explicit STRING-TO-LIST? Or is this really the
> way to go?
>

My inkling is that is is probaly best to avoid the need to turn it into a  
list
in the first place.. But if you must.

(defun string-to-list (string)
   (loop for char across string collect char))

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Tom Russ
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <1131998496.639256.292150@o13g2000cwo.googlegroups.com>
John Thingstad wrote:
>
> My inkling is that is is probaly best to avoid the need to turn it into a
> list
> in the first place..

I have to agree.  It would help if the original poster would tell us
why he wants to turn a string into a list of characters rather than
have it remain what it is:  a vector of characters.  There often is a
better way to solve the real problem that the OP is working on.
From: ··········@bbs.ee.ncu.edu.tw
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <1132304031.826583.152920@g44g2000cwa.googlegroups.com>
Tom Russ wrote:

> I have to agree.  It would help if the original poster would tell us
> why he wants to turn a string into a list of characters rather than
> have it remain what it is:  a vector of characters.  There often is a
> better way to solve the real problem that the OP is working on.

I am very happy to tell that. Conversion between string and list is
needed in
my stupid mind because I think the LISP already fully supports the
computation
of list. I want to take advantage of that and I have developed some
codes as
the following .

The following codes serves as the base stones for building parser for
my daily work.
I am an little Turbo Prolog programmer and depend heavily on some
function such
as fronttoken , frontchar , etc.  Turbo Prolog is an excellent language
but it gets its
limitation of memory (640k , the DOS limitation). Thus I turn to some
language
without that limitation . ARC XLISP-stat is what makes me comfortable.

I have to say that , the development of codes is quite quick even for a
stupid newbie
like me. I hope you all enjoy my codes:

;; Turbo prolog fashioned tokening function in LISP
;; These codes were developed under ARC Xlisp-stat
;; Written and Copyrighted by Oriente 2005-11-14

;; frontchar (extract the first char length from a string)
(defun f1-s (S)
    (cond ((equal S "") "")
          (t (coerce (list (car (coerce S 'list))) 'string))))

;; the rest part after f1-s
(defun f1-r (S)
     (coerce (cdr (coerce S 'list)) 'string))

;; concat 2 strings
(defun append-s (S1 S2)
    (coerce (append (coerce S1 'list) (coerce S2 'list)) 'string))

;; clean the head of the string from a special character
 (defun clean-head (S C)
     (cond ((equal (string C ) (f1-s S)) ( clean-head (f1-r S) C))
           ( t         S)))

;; an element inside a list ?
 (defun in-p (e lst)
    (cond ((equal lst '()) NIL)
          ((equal e (car lst)) T)
          (t      (in-p e (cdr lst)))))

;; string to list
( defun s-2-l (S )
   (cond ((equal S "")  '())
         (t   (coerce S 'list))))

;; list to string
(defun l-2-s (L)       (cond ((equal L '())  "")
         (t   (coerce L 'string))))

;; separate string by a character
(defun token-s (S C)
  (let ( (>CL< (s-2-l S )))
    (cond ((equal (car >CL<) c)     (string C))
          ((equal >CL< '())  "")
          ((equal (cdr >CL<) '())   (L-2-s   >CL<))
          ((equal (cadr >CL<)  c )   (string (car >CL<)))
          ( t   (append-s (f1-s S) (token-s (f1-r S ) c))))))

;; the rest after token-s
(defun token-R (S C)
  (let ( (>CL< (s-2-l S )))
    (cond ((equal (car >CL<) c)     (l-2-s (cdr >CL<)))
          ((equal >CL< '())   "")
          ((equal (cdr >CL<) '()) "")
          ((equal (cadr >CL<)  c )   (l-2-s (cdr >CL<)))
          ( t   (token-R (cdr >CL<) C)))))

;; get the first token , separated by a character
(defun 1-token (S c)
    (token-s (clean-head S c) c))
;;
(defun 1-token-R (S c)
    (token-r (clean-head S c) c))


;;
(defun collect-token (S c)
   (cond ((equal S "")    '())
         ( t     ( cons (1-token S c) (collect-token (1-token-r S c) c
)))))

;; read lines from a file , then collect them to a list
(defun read-file-collect ( file  )
   (with-open-file (instream file :direction :input)
     (let  ((stk ()))
      (loop
       (LET ((>s< (read-line instream NIL)))
          (cond ( (equal >s< nil) (return (reverse stk)))
                ( t (push >s< stk))))))))
;; write lines in a collection to a file
(defun write-file-collect (file stk)
  (with-open-file (stream file :direction :output)
      (loop
        (cond ((equal stk nil) (return))
              (t (format stream "~a~%" (pop stk)))))))

;; find the first separator member in a string
 (defun find-seperator (S cL)
     (cond ((equal s "") nil)
           ((in-p (car (s-2-L S)) cL)
               (car (s-2-L S)))
           ( t  (find-seperator (f1-r S) cL))))

;; collection of token separated by members in separator set
  (defun collect-token-L (s cL)
    (cond ((equal s "") ())
      ( t (let ((>sp<  (FIND-SEPERATOR s cL)))
           (cons (1-token S >sp< )
            (collect-token-L (clean-head (1-token-r S >sp<)>sp< )
CL))))))

;; separate paragraph from a file collect by a biginning token
   (defun para-token (fk token)
  (let ( (>pk< fk)(>rs< ()) (>is< ()))
   (loop
    (cond
      ((equal >pk< ())  (return  (reverse >rs<)))

      ((equal token (car (collect-token-L (car >pk<) '(#\space \t))))
             (push (reverse >is<) >rs<)
             (setf >is< ())
             (push (pop >pk<) >is<))
      (t     (push (pop >pk<) >is<))))))
From: Pascal Bourguignon
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <87k6f65835.fsf@thalassa.informatimago.com>
··········@bbs.ee.ncu.edu.tw writes:

> [...] I think the LISP already fully supports the computation
> of list. I want to take advantage of that and I have developed some
> codes as the following .
> [...] ARC XLISP-stat is what makes me comfortable.


I don't know ARC XLISP-stat, but Common Lisp already fully supports
the computation of strings too.

> ;; frontchar (extract the first char length from a string)
> (defun f1-s (S)
>     (cond ((equal S "") "")
>           (t (coerce (list (car (coerce S 'list))) 'string))))

      (if (string= s "")
          "" ; perhaps you want nil here?
          (char s 0)) ; or (aref s 0) or (elt s 0)
;; for a string is a vector (an array) is a sequence.


> ;; the rest part after f1-s
> (defun f1-r (S)
>      (coerce (cdr (coerce S 'list)) 'string))

       (subseq s 1)


> ;; concat 2 strings
> (defun append-s (S1 S2)
>     (coerce (append (coerce S1 'list) (coerce S2 'list)) 'string))

      (format nil "~A~A" s1 s2) 

;; I first thought of:
;;    (concatenate 'string s1 s2)
;; but it looks like some of your code calls append-s with characters
;; instead of string; concatenate only works with sequence (strings),
;; not characters.



> ;; clean the head of the string from a special character
>  (defun clean-head (S C)
>      (cond ((equal (string C ) (f1-s S)) ( clean-head (f1-r S) C))
>            ( t         S)))

       (string-left-trim (list c) s)

> ;; an element inside a list ?
>  (defun in-p (e lst)
>     (cond ((equal lst '()) NIL)
>           ((equal e (car lst)) T)
>           (t      (in-p e (cdr lst)))))

      (member e lst :test (function equal))


> ;; string to list
> ( defun s-2-l (S )
>    (cond ((equal S "")  '())
>          (t   (coerce S 'list))))
  
     (coerce s 'list)  ; there's no need to special case nil.

> ;; list to string
> (defun l-2-s (L)
>    (cond ((equal L '())  "")
>          (t   (coerce L 'string))))

     (coerce l 'string)  ; there's no need to special case nil.


> ;; separate string by a character
> (defun token-s (S C)
>   (let ( (>CL< (s-2-l S )))
>     (cond ((equal (car >CL<) c)     (string C))
>           ((equal >CL< '())  "")
>           ((equal (cdr >CL<) '())   (L-2-s   >CL<))
>           ((equal (cadr >CL<)  c )   (string (car >CL<)))
>           ( t   (append-s (f1-s S) (token-s (f1-r S ) c))))))

     (subseq s 0 (position c s :test (function equal)))


> ;; the rest after token-s
> (defun token-R (S C)
>   (let ( (>CL< (s-2-l S )))
>     (cond ((equal (car >CL<) c)     (l-2-s (cdr >CL<)))
>           ((equal >CL< '())   "")
>           ((equal (cdr >CL<) '()) "")
>           ((equal (cadr >CL<)  c )   (l-2-s (cdr >CL<)))
>           ( t   (token-R (cdr >CL<) C)))))

    (subseq s (or (position c s :test (function equal)) (length s)))

;; But are you sure you don't want to skip c in the result?


> ;; get the first token , separated by a character
> (defun 1-token (S c)
>     (token-s (clean-head S c) c))
> ;;
> (defun 1-token-R (S c)
>     (token-r (clean-head S c) c))
>
>
> ;;
> (defun collect-token (S c)
>    (cond ((equal S "")    '())
>          ( t     ( cons (1-token S c) (collect-token (1-token-r S c) c
> )))))

(asdf:operate 'asdf:load-op :split-sequence)
(use-package :split-sequence)

     (split-sequence c s :test (function equal))


> ;; read lines from a file , then collect them to a list
> (defun read-file-collect ( file  )
>    (with-open-file (instream file :direction :input)
>      (let  ((stk ()))
>       (loop
>        (LET ((>s< (read-line instream NIL)))
>           (cond ( (equal >s< nil) (return (reverse stk)))
>                 ( t (push >s< stk))))))))

     (with-open-file (instream file :direction :input)
        (loop :for line = (read-line instream nil nil)
              :while line
              :collect line))

> ;; write lines in a collection to a file
> (defun write-file-collect (file stk)
>   (with-open-file (stream file :direction :output)
>       (loop
>         (cond ((equal stk nil) (return))
>               (t (format stream "~a~%" (pop stk)))))))

    (with-open-file (stream file :direction :output
                     :if-exists :supersede :if-does-not-exist :create)
        (format stream "~{~A~%~}" stk))


> ;; find the first separator member in a string
>  (defun find-seperator (S cL)
>      (cond ((equal s "") nil)
>            ((in-p (car (s-2-L S)) cL)
>                (car (s-2-L S)))
>            ( t  (find-seperator (f1-r S) cL))))

       (find-if (lambda (ch) (position ch cl :test (function equal))) s)

;; We use (position ch cl) instead of (member ch cl) to allow passing
;; a sequence instead of just lists for cl, so we can call:
;;  (find-separator "Hello, World!" " .,;!?")


> ;; collection of token separated by members in separator set
>   (defun collect-token-L (s cL)
>     (cond ((equal s "") ())
>       ( t (let ((>sp<  (FIND-SEPERATOR s cL)))
>            (cons (1-token S >sp< )
>             (collect-token-L (clean-head (1-token-r S >sp<)>sp< )
> CL))))))

    (split-sequence-if (lambda (ch) (position ch cl :test (function equal))) s)


> ;; separate paragraph from a file collect by a biginning token
>    (defun para-token (fk token)
>   (let ( (>pk< fk)(>rs< ()) (>is< ()))
>    (loop
>     (cond
>       ((equal >pk< ())  (return  (reverse >rs<)))
>
>       ((equal token (car (collect-token-L (car >pk<) '(#\space \t))))
>              (push (reverse >is<) >rs<)
>              (setf >is< ())
>              (push (pop >pk<) >is<))
>       (t     (push (pop >pk<) >is<))))))
>

Left as an exercice ;-)


If ARC XLISP-stat doesn't offer the same string processing support,
perhaps you could switch to Common Lisp?


-- 
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
__Pascal Bourguignon__                     http://www.informatimago.com/
From: ··········@bbs.ee.ncu.edu.tw
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <1132327349.667713.140130@g44g2000cwa.googlegroups.com>
Pascal , thanks for your masterpiece of codes. I learned a lot from
your codes.
 My codes , as I have confessed , are simple-minded and may seem
somewhat stupid . This is because I am new to Lisp. But even for a
newbie like me, lisp help me a lot
in saving developing time . And each function can be tested immediately
after definition,
that helps a lot in debugging. I wish more and more people can find and
enjoy lisp.

Thanks again , Pascal !!
From: Pascal Bourguignon
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <873blu53z0.fsf@thalassa.informatimago.com>
··········@bbs.ee.ncu.edu.tw writes:

> Pascal , thanks for your masterpiece of codes. I learned a lot from
> your codes.
>  My codes , as I have confessed , are simple-minded and may seem
> somewhat stupid . This is because I am new to Lisp. But even for a
> newbie like me, lisp help me a lot
> in saving developing time . And each function can be tested immediately
> after definition,
> that helps a lot in debugging. I wish more and more people can find and
> enjoy lisp.
>
> Thanks again , Pascal !!

Be sure to browse: http://www.cliki.net/
                   http://www.cliki.net/admin/search?words=tutorial
                   http://www.cliki.net/Education
etc...

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
The mighty hunter
Returns with gifts of plump birds,
Your foot just squashed one.
From: Pascal Bourguignon
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <87psp3jc2w.fsf@thalassa.informatimago.com>
"John Thingstad" <··············@chello.no> writes:

> On Mon, 14 Nov 2005 17:38:42 +0100, Bruce Butterfield
> <·····@open-tek.com>  wrote:
>
>> I was under the impression that COERCE is a 'big gun' technique much
>> akin to EVAL which is to be used only when there are no reasonable
>> alternatives (Graham's  'ANSI Common Lisp' pg. 162). Wouldn't it be
>> prefereable to write an explicit STRING-TO-LIST? Or is this really the
>> way to go?
>>
>
> My inkling is that is is probaly best to avoid the need to turn it
> into a  list
> in the first place.. But if you must.
>
> (defun string-to-list (string)
>    (loop for char across string collect char))

It depends on your implemenation. For example:

In clisp, coerce is best:

[79]> (defun test (n) 
        (let ((s (make-string n :initial-element #\a)))
        (print 'coerce) (time (dotimes (i n) (coerce s 'list)))
        (print 'map) (time (dotimes (i n) (map 'list (function identity) s)))
        (print 'loop) (time (dotimes (i n) (loop for c across s collect c)))))
TEST
[80]> (compile 'test)
TEST ;
NIL ;
NIL
[81]> (test 10000)

COERCE 
Real time: 0.001672 sec.
Run time: 0.0 sec.
Space: 0 Bytes
MAP 
Real time: 149.69267 sec.
Run time: 103.17 sec.
Space: 800000000 Bytes
GC: 994, GC time: 31.52 sec.
LOOP 
Real time: 116.69872 sec.
Run time: 77.33 sec.
Space: 800000000 Bytes
GC: 995, GC time: 31.27 sec.
NIL
[82]> 


In sbcl, loop is best:


* (defun test (n) 
        (let ((s (make-string n :initial-element #\a)))
        (print 'coerce) (time (dotimes (i n) (coerce s 'list)))
        (print 'map) (time (dotimes (i n) (map 'list (function identity) s)))
        (print 'loop) (time (dotimes (i n) (loop for c across s collect c)))))
STYLE-WARNING: redefining TEST in DEFUN

TEST
* (compile 'test)

TEST
NIL
NIL
* (test 10000)

COERCE 
Evaluation took:
  22.65 seconds of real time
  20.63 seconds of user run time
  0.97 seconds of system run time
  0 page faults and
  800,084,592 bytes consed.

MAP 
Evaluation took:
  26.309 seconds of real time
  21.78 seconds of user run time
  1.06 seconds of system run time
  0 page faults and
  799,998,896 bytes consed.

LOOP 
Evaluation took:
  8.327 seconds of real time
  6.97 seconds of user run time
  1.08 seconds of system run time
  0 page faults and
  800,082,976 bytes consed.
NIL
* 



Perhaps we could write:

(defun string-to-list (s)
  #.(macrolet ((rtime (&body body)
                 `(let ((fun (compile nil (lambda () ,@body)))
                        (start (get-internal-run-time)))
                    (funcall fun)
                    (- (get-internal-run-time) start))))
      (let* ((n 1000)
             (s (make-string n :initial-element #\a))
             (c (rtime (dotimes (i n) #1=(coerce s 'list))))
             (m (rtime (dotimes (i n) #2=(map 'list (function identity) s))))
             (l (rtime (dotimes (i n) #3=(loop for c across s collect c)))))
        (cond
          ((and (< c m) (< c l)) '#1#)
          ((and (< m c) (< m l)) '#2#)
          (t                     '#3#)))))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: Christophe Rhodes
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <sq1x1jge0j.fsf@cam.ac.uk>
Pascal Bourguignon <····@mouse-potato.com> writes:

> It depends on your implemenation. For example:
>
> In clisp, coerce is best:
>
> COERCE 
> Real time: 0.001672 sec.
> Run time: 0.0 sec.
> Space: 0 Bytes

I don't think you have timed what you think you have timed.

Christophe
From: Pascal Bourguignon
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <87ek5jj59k.fsf@thalassa.informatimago.com>
Christophe Rhodes <·····@cam.ac.uk> writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
>
>> It depends on your implemenation. For example:
>>
>> In clisp, coerce is best:
>>
>> COERCE 
>> Real time: 0.001672 sec.
>> Run time: 0.0 sec.
>> Space: 0 Bytes
>
> I don't think you have timed what you think you have timed.

It doesn't matter.  The precise benchmark would be more artificial.
It shows that if you can use a function known to the compiler instead
of one of yours, you'd better use the function known by the compiler.

And anyways, in clisp most functions in COMMON-LISP are implemented in
C, while user functions run on the virtual machine.



[94]> (defun test (n s) 
        (print 'coerce) (time (dotimes (i n) (coerce s 'list)))
        (print 'map) (time (dotimes (i n) (map 'list (function identity) s)))
        (print 'loop) (time (dotimes (i n) (loop for c across s collect c))))
TEST
[95]> (test 1000 (make-string 1000 :initial-element #\a))

COERCE 
Real time: 0.807245 sec.
Run time: 0.76 sec.
Space: 8000000 Bytes
GC: 10, GC time: 0.32 sec.
MAP 
Real time: 1.144332 sec.
Run time: 1.0 sec.
Space: 8000000 Bytes
GC: 10, GC time: 0.31 sec.
LOOP 
Real time: 6.922478 sec.
Run time: 5.03 sec.
Space: 8000000 Bytes
GC: 10, GC time: 0.3 sec.
NIL
[96]> 

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
From: Thomas A. Russ
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <ymizmo4pdjm.fsf@sevak.isi.edu>
Pascal Bourguignon <····@mouse-potato.com> writes:

> It doesn't matter.  The precise benchmark would be more artificial.
> It shows that if you can use a function known to the compiler instead
> of one of yours, you'd better use the function known by the compiler.

I suppose this is clear from context, but all the discussion about
INTERSECTION and UNION in another thread points out that not all
functions known to the compiler can beat your own hand-crafted
functions, particularly if there are additional restrictions that you
can impose to provide a more efficient interface.

> And anyways, in clisp most functions in COMMON-LISP are implemented in
> C, while user functions run on the virtual machine.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: John Thingstad
Subject: Re: The way to access the slots of the class STRING
Date: 
Message-ID: <op.sz8ww406pqzri1@mjolner.upc.no>
On Mon, 14 Nov 2005 19:53:11 +0100, Pascal Bourguignon  
<····@mouse-potato.com> wrote:

Simularly on LispWorks

CL-USER 4 > (test 10000)

COERCE
Timing the evaluation of (DOTIMES (I N) (COERCE S (QUOTE LIST)))

user time    =     34.968
system time  =      0.000
Elapsed time =   0:00:35
Allocation   = 4096 bytes standard / 1100113564 bytes conses
0 Page faults

MAP
Timing the evaluation of (DOTIMES (I N) (MAP (QUOTE LIST) (FUNCTION  
IDENTITY) S))

user time    =     38.703
system time  =      0.015
Elapsed time =   0:00:40
Allocation   = 39968 bytes standard / 1100019129 bytes conses
0 Page faults

LOOP
Timing the evaluation of (DOTIMES (I N) (LOOP FOR C ACROSS S COLLECT C))

user time    =     32.781
system time  =      0.000
Elapsed time =   0:00:33
Allocation   = 8912 bytes standard / 1100114521 bytes conses
0 Page faults
NIL

On ACL

CG-USER(2): (test 10000)

COERCE
; cpu time (non-gc) 21,017 msec user, 110 msec system
; cpu time (gc)     6,155 msec user, 0 msec system
; cpu time (total)  27,172 msec user, 110 msec system
; real time  29,688 msec
; space allocation:
;  100,000,803 cons cells, 344 other bytes, 0 static bytes
MAP
; cpu time (non-gc) 25,822 msec user, 93 msec system
; cpu time (gc)     6,256 msec user, 16 msec system
; cpu time (total)  32,078 msec user, 109 msec system
; real time  33,625 msec
; space allocation:
;  100,003,010 cons cells, 28,280 other bytes, 0 static bytes
LOOP
; cpu time (non-gc) 24,239 msec user, 16 msec system
; cpu time (gc)     5,808 msec user, 0 msec system
; cpu time (total)  30,047 msec user, 16 msec system
; real time  30,594 msec
; space allocation:
;  100,010,819 cons cells, 0 other bytes, 0 static bytes
NIL

So on ACL coerce is faster!

(Running on Windows XP with a Intel Celeron 2.4 GHz)

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/