From: cametan
Subject: About Clisp
Date: 
Message-ID: <3ce216a8-25d8-450e-81fe-f15d83605555@r37g2000prm.googlegroups.com>
I don't know where to post, then please let me post this here.

I am using clisp 2.45 on Windows XP, and I found something strange.

On Common Lisp, I believe that the S-expression below

(cons '(a b c d) nil)

or something like below

(cons '(a b c d) '())

is evaluated like this.

((a b c d))

However, when I wrote a script like this:

(defun pack (ls)
  (labels ((foo (ls0 ls1 ls2)
             (let ((x (car ls0))
                   (y (car ls1)))
               (cond ((null ls0)
                      (reverse (cons ls1 ls2))) ;;;This returns result
of its calculation
                     ((eq x y)
                      (foo (cdr ls0) (cons x ls1) ls2))
                     (t
                      (foo (cdr ls0) (cons x nil) (cons ls1
ls2)))))));;;Does the 2nd args of recursive have some problem?
    (foo ls '() '())))

and made it run; for instance, it gave

CL-USER> (pack '(a a a a b c c a a d e e e e))
(NIL (A A A A) (B) (C C) (A A) (D) (E E E E))

and cons of the list seemed to have unnecessary NIL.

I'm not sure if it is a bug on clisp.
Please give me some advice.

Sorry about my strange English. (I'm not a native speaker)

From: Tayssir John Gabbour
Subject: Re: About Clisp
Date: 
Message-ID: <c49de254-90e3-4b24-8002-0f5d052da521@m3g2000hsc.googlegroups.com>
On Jun 22, 9:47 am, cametan <··············@gmail.com> wrote:
> I don't know where to post, then please let me post this here.

No problem!


> CL-USER> (pack '(a a a a b c c a a d e e e e))
> (NIL (A A A A) (B) (C C) (A A) (D) (E E E E))
>
> and cons of the list seemed to have unnecessary NIL.

Try to see what the function FOO is doing, using TRACE. Let's refactor
out FOO into its own function:

(defun pack-helper (ls0 ls1 ls2)
             (let ((x (car ls0))
                   (y (car ls1)))
               (cond ((null ls0)
                      ;; This returns result of its calculation
                      (reverse (cons ls1 ls2)))
                     ((eq x y)
                      (pack-helper (cdr ls0) (cons x ls1) ls2))
                     (t
                      (pack-helper (cdr ls0)
                           (cons x nil)
                           (cons ls1
                                 ;; Does the 2nd args of recursive
                                 ;; have some problem?
                                 ls2))))))

(defun pack (ls)
  (pack-helper ls '() '()))


CL-USER> (trace pack-helper)
(PACK-HELPER)
CL-USER> (pack '(a a a a b c c a a d e e e e))
;;; ... here it should become clear ...



> I'm not sure if it is a bug on clisp.
> Please give me some advice.

Yes, whenever I stop trusting software, because it was hard to install
or something, I start thinking the bug lies with the underlying
software. ;)


Tayssir
From: Tayssir John Gabbour
Subject: Re: About Clisp
Date: 
Message-ID: <9e572fa3-77c8-43e8-a80c-9178faa192a7@c58g2000hsc.googlegroups.com>
On Jun 22, 11:01 am, Tayssir John Gabbour
<············@googlemail.com> wrote:
> Try to see what the function FOO is doing, using TRACE. Let's refactor
> out FOO into its own function:
>
> (defun pack-helper (ls0 ls1 ls2)
>              (let ((x (car ls0))
>                    (y (car ls1)))

Argh, I poorly indented that! ;)

Tayssir
From: cametan
Subject: Re: About Clisp
Date: 
Message-ID: <e7bdd579-72e1-4b4a-ba6c-b2cd050690b3@z24g2000prf.googlegroups.com>
On 6¤ë22¤é, ¤È«á6:01, Tayssir John Gabbour <············@googlemail.com>
wrote:
> On Jun 22, 9:47 am, cametan <··············@gmail.com> wrote:
>
> > I don't know where to post, then please let me post this here.
>
> No problem!
>
> > CL-USER> (pack '(a a a a b c c a a d e e e e))
> > (NIL (A A A A) (B) (C C) (A A) (D) (E E E E))
>
> > and cons of the list seemed to have unnecessary NIL.
>
> Try to see what the function FOO is doing, using TRACE. Let's refactor
> out FOO into its own function:
>
> (defun pack-helper (ls0 ls1 ls2)
>              (let ((x (car ls0))
>                    (y (car ls1)))
>                (cond ((null ls0)
>                       ;; This returns result of its calculation
>                       (reverse (cons ls1 ls2)))
>                      ((eq x y)
>                       (pack-helper (cdr ls0) (cons x ls1) ls2))
>                      (t
>                       (pack-helper (cdr ls0)
>                            (cons x nil)
>                            (cons ls1
>                                  ;; Does the 2nd args of recursive
>                                  ;; have some problem?
>                                  ls2))))))
>
> (defun pack (ls)
>   (pack-helper ls '() '()))
>
> CL-USER> (trace pack-helper)
> (PACK-HELPER)
> CL-USER> (pack '(a a a a b c c a a d e e e e))
> ;;; ... here it should become clear ...
>
> > I'm not sure if it is a bug on clisp.
> > Please give me some advice.
>
> Yes, whenever I stop trusting software, because it was hard to install
> or something, I start thinking the bug lies with the underlying
> software. ;)
>
> Tayssir

Thanks, mr Tayssir.
So, is it O.K. to think clisp has some bug around cons?
From: Pascal J. Bourguignon
Subject: Re: About Clisp
Date: 
Message-ID: <87tzflaf4h.fsf@hubble.informatimago.com>
cametan <··············@gmail.com> writes:

> Thanks, mr Tayssir.
> So, is it O.K. to think clisp has some bug around cons?

No, it is not.  The bug is in your code.

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

CAUTION: The mass of this product contains the energy equivalent of
85 million tons of TNT per net ounce of weight.
From: cametan
Subject: Re: About Clisp
Date: 
Message-ID: <0f06c9ce-c697-45d8-ba06-f97972f2403e@w4g2000prd.googlegroups.com>
On 6¤ë22¤é, ¤È«á8:22, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> cametan <··············@gmail.com> writes:
> > Thanks, mr Tayssir.
> > So, is it O.K. to think clisp has some bug around cons?
>
> No, it is not.  The bug is in your code.
>
> --
> __Pascal Bourguignon__                    http://www.informatimago.com/
>
> CAUTION: The mass of this product contains the energy equivalent of
> 85 million tons of TNT per net ounce of weight.

>> Mr Pascal Bourguignon

¡ÖNo, it is not.  The bug is in your code.

Now I understand.
Thanks for your advice.
From: Kojak
Subject: Re: About Clisp
Date: 
Message-ID: <20080622104347.49a8d0cb@thor.janville.org>
Le Sun, 22 Jun 2008 00:47:24 -0700 (PDT),
cametan <··············@gmail.com> a écrit :

> However, when I wrote a script like this:
> (defun pack (ls)
>   [...]
>     )
> 
> and made it run; for instance, it gave
> 
> CL-USER> (pack '(a a a a b c c a a d e e e e))
> (NIL (A A A A) (B) (C C) (A A) (D) (E E E E))
> 
> and cons of the list seemed to have unnecessary NIL.

It seems that you try to do some RLE encoding related
stuff.

Have a look on something like '99 lisp problems' with
your favorite search engine. ;-)


-- 
Jacques.
From: cametan
Subject: Re: About Clisp
Date: 
Message-ID: <7de63a3b-1841-4c74-afb4-3fdb5ec2d6a0@r37g2000prm.googlegroups.com>
On 6ÔÂ22ÈÕ, Îçáá5:43, Kojak <·······@janville.Borg.invalid> wrote:
> Le Sun, 22 Jun 2008 00:47:24 -0700 (PDT),
> cametan <··············@gmail.com> a ¨¦crit :
>
> > However, when I wrote a script like this:
> > (defun pack (ls)
> >   [...]
> >     )
>
> > and made it run; for instance, it gave
>
> > CL-USER> (pack '(a a a a b c c a a d e e e e))
> > (NIL (A A A A) (B) (C C) (A A) (D) (E E E E))
>
> > and cons of the list seemed to have unnecessary NIL.
>
> It seems that you try to do some RLE encoding related
> stuff.
>
> Have a look on something like '99 lisp problems' with
> your favorite search engine. ;-)
>
> --
> Jacques.

>> Mr.Jacques

Thanks for your advice.

Actually. as you mentioned, I just try solving one of '99 lisp
problems.
And I found some strange attitude of Clisp.

For instance, I rewrote my code for it by using DO as usual Common
Lisper's way

;;;Rewritten Version with do

(defun pack (ls)
  (do ((ls0 ls (cdr ls0))
       (ls1 nil (if (eql (car ls0) (car ls1))
                    (cons (car ls0) ls1)
                    (cons (car ls0) nil)))
       (ls2 nil (if (eql (car ls0) (car ls1))
                    ls2
                    (cons ls1 ls2))))
      ((null ls0) (reverse (cons ls1 ls2)))))

;;;evaluation

CL-USER> (pack '(a a a a b c c a a d d e e e e))
(NIL (A A A A) (B) (C C) (A A) (D D) (E E E E))
CL-USER>

;;;

As you see, same thing happens.
So I thought there is a bug around CONS on clisp.
From: Pascal J. Bourguignon
Subject: Re: About Clisp
Date: 
Message-ID: <873an5byqo.fsf@hubble.informatimago.com>
cametan <··············@gmail.com> writes:

> I don't know where to post, then please let me post this here.
>
> I am using clisp 2.45 on Windows XP, and I found something strange.


So you want us to debug your code...



> However, when I wrote a script like this:
>
> (defun pack (ls)
>   (labels ((foo (ls0 ls1 ls2)
>              (let ((x (car ls0))
>                    (y (car ls1)))
>                (cond ((null ls0)
>                       (reverse (cons ls1 ls2))) ;;;This returns result
> of its calculation
>                      ((eq x y)
>                       (foo (cdr ls0) (cons x ls1) ls2))
>                      (t
>                       (foo (cdr ls0) (cons x nil) (cons ls1
> ls2)))))));;;Does the 2nd args of recursive have some problem?
>     (foo ls '() '())))
>
> and made it run; for instance, it gave
>
> CL-USER> (pack '(a a a a b c c a a d e e e e))
> (NIL (A A A A) (B) (C C) (A A) (D) (E E E E))
>
> and cons of the list seemed to have unnecessary NIL.
>
> I'm not sure if it is a bug on clisp.
> Please give me some advice.
>
> Sorry about my strange English. (I'm not a native speaker)

One debugging problem you have here is in the use of LABELS.  You
cannot use CL:TRACE on local functions.  You have the choice between
moving (temporarily) the FOO function to global scope (define it with
DEFUN instead of LABELS), or using a macro like TRACE-LABELS instead
of LABELS.  Then it is obvious where the problem comes from:


;; From http://darcs.informatimago.com/public/lisp/common-lisp/
C/USER[37]> (use-package :com.informatimago.common-lisp.utility) 
T
C/USER[38]> (defun pack (ls)
              (tracing-labels
               ((foo (ls0 ls1 ls2)
                     (let ((x (car ls0))
                           (y (car ls1)))
                       (cond ((null ls0)
                              ;; This returns result of its calculation
                              (reverse (cons ls1 ls2))) 
                             ((eq x y)
                              (foo (cdr ls0) (cons x ls1) ls2))
                             (t
                              ;; Does the 2nd args of recursive have some problem?
                              (foo (cdr ls0) (cons x nil) (cons ls1 ls2))))))) 
               (foo ls '() '())))
PACK
C/USER[39]> (pack '(a a b c c))
Entering FOO (:LS0 (A A B C C) :LS1 NIL :LS2 NIL)
Entering FOO (:LS0 (A B C C) :LS1 (A) :LS2 (NIL)) ; <<-- Here.
Entering FOO (:LS0 (B C C) :LS1 (A A) :LS2 (NIL))
Entering FOO (:LS0 (C C) :LS1 (B) :LS2 ((A A) NIL))
Entering FOO (:LS0 (C) :LS1 (C) :LS2 ((B) (A A) NIL))
Entering FOO (:LS0 NIL :LS1 (C C) :LS2 ((B) (A A) NIL))
Exiting FOO --> (NIL (A A) (B) (C C))
Unwinding FOO
Exiting FOO --> (NIL (A A) (B) (C C))
Unwinding FOO
Exiting FOO --> (NIL (A A) (B) (C C))
Unwinding FOO
Exiting FOO --> (NIL (A A) (B) (C C))
Unwinding FOO
Exiting FOO --> (NIL (A A) (B) (C C))
Unwinding FOO
Exiting FOO --> (NIL (A A) (B) (C C))
Unwinding FOO
(NIL (A A) (B) (C C))
C/USER[40]> 

So when we (cons ls1 ls2) the first time, ls1 is NIL and this is wrong.

C/USER[40]> (defun pack (ls)
              (tracing-labels
               ((foo (ls0 ls1 ls2)
                     (let ((x (car ls0))
                           (y (car ls1)))
                       (cond ((null ls0)
                              ;; This returns result of its calculation
                              (reverse (if ls1 (cons ls1 ls2) ls2))) 
                             ((eq x y)
                              (foo (cdr ls0) (cons x ls1) ls2))
                             (t
                              ;; Does the 2nd args of recursive have some problem?
                              (foo (cdr ls0) (cons x nil) (if ls1 (cons ls1 ls2) ls2))))))) 
               (foo ls '() '())))
PACK
C/USER[41]> (pack '(a a b c c))
Entering FOO (:LS0 (A A B C C) :LS1 NIL :LS2 NIL)
Entering FOO (:LS0 (A B C C) :LS1 (A) :LS2 NIL)
Entering FOO (:LS0 (B C C) :LS1 (A A) :LS2 NIL)
Entering FOO (:LS0 (C C) :LS1 (B) :LS2 ((A A)))
Entering FOO (:LS0 (C) :LS1 (C) :LS2 ((B) (A A)))
Entering FOO (:LS0 NIL :LS1 (C C) :LS2 ((B) (A A)))
Exiting FOO --> ((A A) (B) (C C))
Unwinding FOO
Exiting FOO --> ((A A) (B) (C C))
Unwinding FOO
Exiting FOO --> ((A A) (B) (C C))
Unwinding FOO
Exiting FOO --> ((A A) (B) (C C))
Unwinding FOO
Exiting FOO --> ((A A) (B) (C C))
Unwinding FOO
Exiting FOO --> ((A A) (B) (C C))
Unwinding FOO
((A A) (B) (C C))
C/USER[42]> 


> On Common Lisp, I believe that the S-expression below
>
> (cons '(a b c d) nil)
>
> or something like below
>
> (cons '(a b c d) '())
>
> is evaluated like this.
>
> ((a b c d))

This is correct.  But you are calling (cons '() nil) --> (nil)
and then: (cons '(a a a) '(nil)) --> ((a a a) nil) 

-- 
__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: cametan
Subject: Re: About Clisp
Date: 
Message-ID: <9aa4b41d-99c9-47e1-a186-368020d8f843@q24g2000prf.googlegroups.com>
On 6¤ë22¤é, ¤È«á6:33, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> cametan <··············@gmail.com> writes:
> > I don't know where to post, then please let me post this here.
>
> > I am using clisp 2.45 on Windows XP, and I found something strange.
>
> So you want us to debug your code...
>
>
>
> > However, when I wrote a script like this:
>
> > (defun pack (ls)
> >   (labels ((foo (ls0 ls1 ls2)
> >              (let ((x (car ls0))
> >                    (y (car ls1)))
> >                (cond ((null ls0)
> >                       (reverse (cons ls1 ls2))) ;;;This returns result
> > of its calculation
> >                      ((eq x y)
> >                       (foo (cdr ls0) (cons x ls1) ls2))
> >                      (t
> >                       (foo (cdr ls0) (cons x nil) (cons ls1
> > ls2)))))));;;Does the 2nd args of recursive have some problem?
> >     (foo ls '() '())))
>
> > and made it run; for instance, it gave
>
> > CL-USER> (pack '(a a a a b c c a a d e e e e))
> > (NIL (A A A A) (B) (C C) (A A) (D) (E E E E))
>
> > and cons of the list seemed to have unnecessary NIL.
>
> > I'm not sure if it is a bug on clisp.
> > Please give me some advice.
>
> > Sorry about my strange English. (I'm not a native speaker)
>
> One debugging problem you have here is in the use of LABELS.  You
> cannot use CL:TRACE on local functions.  You have the choice between
> moving (temporarily) the FOO function to global scope (define it with
> DEFUN instead of LABELS), or using a macro like TRACE-LABELS instead
> of LABELS.  Then it is obvious where the problem comes from:
>
> ;; Fromhttp://darcs.informatimago.com/public/lisp/common-lisp/
> C/USER[37]> (use-package :com.informatimago.common-lisp.utility)
> T
> C/USER[38]> (defun pack (ls)
>               (tracing-labels
>                ((foo (ls0 ls1 ls2)
>                      (let ((x (car ls0))
>                            (y (car ls1)))
>                        (cond ((null ls0)
>                               ;; This returns result of its calculation
>                               (reverse (cons ls1 ls2)))
>                              ((eq x y)
>                               (foo (cdr ls0) (cons x ls1) ls2))
>                              (t
>                               ;; Does the 2nd args of recursive have some problem?
>                               (foo (cdr ls0) (cons x nil) (cons ls1 ls2)))))))
>                (foo ls '() '())))
> PACK
> C/USER[39]> (pack '(a a b c c))
> Entering FOO (:LS0 (A A B C C) :LS1 NIL :LS2 NIL)
> Entering FOO (:LS0 (A B C C) :LS1 (A) :LS2 (NIL)) ; <<-- Here.
> Entering FOO (:LS0 (B C C) :LS1 (A A) :LS2 (NIL))
> Entering FOO (:LS0 (C C) :LS1 (B) :LS2 ((A A) NIL))
> Entering FOO (:LS0 (C) :LS1 (C) :LS2 ((B) (A A) NIL))
> Entering FOO (:LS0 NIL :LS1 (C C) :LS2 ((B) (A A) NIL))
> Exiting FOO --> (NIL (A A) (B) (C C))
> Unwinding FOO
> Exiting FOO --> (NIL (A A) (B) (C C))
> Unwinding FOO
> Exiting FOO --> (NIL (A A) (B) (C C))
> Unwinding FOO
> Exiting FOO --> (NIL (A A) (B) (C C))
> Unwinding FOO
> Exiting FOO --> (NIL (A A) (B) (C C))
> Unwinding FOO
> Exiting FOO --> (NIL (A A) (B) (C C))
> Unwinding FOO
> (NIL (A A) (B) (C C))
> C/USER[40]>
>
> So when we (cons ls1 ls2) the first time, ls1 is NIL and this is wrong.
>
> C/USER[40]> (defun pack (ls)
>               (tracing-labels
>                ((foo (ls0 ls1 ls2)
>                      (let ((x (car ls0))
>                            (y (car ls1)))
>                        (cond ((null ls0)
>                               ;; This returns result of its calculation
>                               (reverse (if ls1 (cons ls1 ls2) ls2)))
>                              ((eq x y)
>                               (foo (cdr ls0) (cons x ls1) ls2))
>                              (t
>                               ;; Does the 2nd args of recursive have some problem?
>                               (foo (cdr ls0) (cons x nil) (if ls1 (cons ls1 ls2) ls2)))))))
>                (foo ls '() '())))
> PACK
> C/USER[41]> (pack '(a a b c c))
> Entering FOO (:LS0 (A A B C C) :LS1 NIL :LS2 NIL)
> Entering FOO (:LS0 (A B C C) :LS1 (A) :LS2 NIL)
> Entering FOO (:LS0 (B C C) :LS1 (A A) :LS2 NIL)
> Entering FOO (:LS0 (C C) :LS1 (B) :LS2 ((A A)))
> Entering FOO (:LS0 (C) :LS1 (C) :LS2 ((B) (A A)))
> Entering FOO (:LS0 NIL :LS1 (C C) :LS2 ((B) (A A)))
> Exiting FOO --> ((A A) (B) (C C))
> Unwinding FOO
> Exiting FOO --> ((A A) (B) (C C))
> Unwinding FOO
> Exiting FOO --> ((A A) (B) (C C))
> Unwinding FOO
> Exiting FOO --> ((A A) (B) (C C))
> Unwinding FOO
> Exiting FOO --> ((A A) (B) (C C))
> Unwinding FOO
> Exiting FOO --> ((A A) (B) (C C))
> Unwinding FOO
> ((A A) (B) (C C))
> C/USER[42]>
>
> > On Common Lisp, I believe that the S-expression below
>
> > (cons '(a b c d) nil)
>
> > or something like below
>
> > (cons '(a b c d) '())
>
> > is evaluated like this.
>
> > ((a b c d))
>
> This is correct.  But you are calling (cons '() nil) --> (nil)
> and then: (cons '(a a a) '(nil)) --> ((a a a) nil)
>
> --
> __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.

>>Mr. Pascal Bourguignon.

Thanks for your advice.

¡ÖSo you want us to debug your code...

No, I did not mean it.
I've just thought Clisp had a bug.
Now I see it was my mistake. I'm so sorry.

> One debugging problem you have here is in the use of LABELS.  You
> cannot use CL:TRACE on local functions.  You have the choice between
> moving (temporarily) the FOO function to global scope (define it with
> DEFUN instead of LABELS), or using a macro like TRACE-LABELS instead
> of LABELS.  Then it is obvious where the problem comes from:

Thanks to tell me how to trace local functions. I really appreciate.
Leaning Scheme, my favorite way becomes using local functions. But it
does not seem a good way now, though.

> Entering FOO (:LS0 (A B C C) :LS1 (A) :LS2 (NIL)) ; <<-- Here.
> This is correct.  But you are calling (cons '() nil) --> (nil)
>  and then: (cons '(a a a) '(nil)) --> ((a a a) nil)

(cons nil '()) occurs......I did not imagine it.
Thank you very much, and thanks you all guys here, too.
I keep leaning Common Lisp.
From: John Thingstad
Subject: Re: About Clisp
Date: 
Message-ID: <op.uc5a2ugmut4oq5@pandora.alfanett.no>
P� Sun, 22 Jun 2008 09:47:24 +0200, skrev cametan  
<··············@gmail.com>:

> I don't know where to post, then please let me post this here.
>
> I am using clisp 2.45 on Windows XP, and I found something strange.
>
> On Common Lisp, I believe that the S-expression below
>
> (cons '(a b c d) nil)
>
> or something like below
>
> (cons '(a b c d) '())
>
> is evaluated like this.
>
> ((a b c d))
>
> However, when I wrote a script like this:
>
> (defun pack (ls)
>   (labels ((foo (ls0 ls1 ls2)
>              (let ((x (car ls0))
>                    (y (car ls1)))
>                (cond ((null ls0)
>                       (reverse (cons ls1 ls2))) ;;;This returns result
> of its calculation
>                      ((eq x y)
>                       (foo (cdr ls0) (cons x ls1) ls2))
>                      (t
>                       (foo (cdr ls0) (cons x nil) (cons ls1
> ls2)))))));;;Does the 2nd args of recursive have some problem?
>     (foo ls '() '())))
>
> and made it run; for instance, it gave
>
> CL-USER> (pack '(a a a a b c c a a d e e e e))
> (NIL (A A A A) (B) (C C) (A A) (D) (E E E E))
>
> and cons of the list seemed to have unnecessary NIL.
>
> I'm not sure if it is a bug on clisp.
> Please give me some advice.
>
> Sorry about my strange English. (I'm not a native speaker)

I have a devil of a time understanding your code.
After translating it I came up with:

(defun pack (list)
   (labels ((build (source sub-list result)
              (let ((current (first source))
                    (previous (first sub-list)))
                (cond ((null source)
                       (nreverse (cons sub-list result)))
                      ((eql current previous)
                       (build (rest source) (cons current sub-list) result))
                      (t
                       (build (rest source) (cons current nil)
                              (if (consp sub-list) (cons sub-list result)  
result))))))) ; this is different
     (build list nil nil)))

The problem came from cons'ing ls1 to ls2 the first time the function is  
called when ls1 is nil.
The code here corrects the problem.
This way of solving the problem using tail recursion and accumulators is  
very Scheem'ish.
Here is a more Lisp'ish solution.

(defun pack (list)
   (let (result-list sub-list)
     (do ((current list (rest current))
          (previous nil current))
         ((null current)
          (push sub-list result-list)
          (nreverse result-list))
       (when (and (not (eql (first current) (first previous))) (consp  
sub-list))
         (push sub-list result-list)
         (setf sub-list nil))
       (push (first current) sub-list))))

Also note the use of eql rather than eq. This works for characters and  
numbers as well and should be used instead.
nreverse is more efficient than reverse and since you are cons'ing up a  
new list anyhow safe.

--------------
John Thingstad
From: cametan
Subject: Re: About Clisp
Date: 
Message-ID: <0ded1058-80ee-412b-9d95-1c41e8547b3d@y22g2000prd.googlegroups.com>
On 6月22日, 午後7:21, "John Thingstad" <·······@online.no> wrote:
> På Sun, 22 Jun 2008 09:47:24 +0200, skrev cametan  
> <··············@gmail.com>:
>
>
>
> > I don't know where to post, then please let me post this here.
>
> > I am using clisp 2.45 on Windows XP, and I found something strange.
>
> > On Common Lisp, I believe that the S-expression below
>
> > (cons '(a b c d) nil)
>
> > or something like below
>
> > (cons '(a b c d) '())
>
> > is evaluated like this.
>
> > ((a b c d))
>
> > However, when I wrote a script like this:
>
> > (defun pack (ls)
> >   (labels ((foo (ls0 ls1 ls2)
> >              (let ((x (car ls0))
> >                    (y (car ls1)))
> >                (cond ((null ls0)
> >                       (reverse (cons ls1 ls2))) ;;;This returns result
> > of its calculation
> >                      ((eq x y)
> >                       (foo (cdr ls0) (cons x ls1) ls2))
> >                      (t
> >                       (foo (cdr ls0) (cons x nil) (cons ls1
> > ls2)))))));;;Does the 2nd args of recursive have some problem?
> >     (foo ls '() '())))
>
> > and made it run; for instance, it gave
>
> > CL-USER> (pack '(a a a a b c c a a d e e e e))
> > (NIL (A A A A) (B) (C C) (A A) (D) (E E E E))
>
> > and cons of the list seemed to have unnecessary NIL.
>
> > I'm not sure if it is a bug on clisp.
> > Please give me some advice.
>
> > Sorry about my strange English. (I'm not a native speaker)
>
> I have a devil of a time understanding your code.
> After translating it I came up with:
>
> (defun pack (list)
>    (labels ((build (source sub-list result)
>               (let ((current (first source))
>                     (previous (first sub-list)))
>                 (cond ((null source)
>                        (nreverse (cons sub-list result)))
>                       ((eql current previous)
>                        (build (rest source) (cons current sub-list) result))
>                       (t
>                        (build (rest source) (cons current nil)
>                               (if (consp sub-list) (cons sub-list result)  
> result))))))) ; this is different
>      (build list nil nil)))
>
> The problem came from cons'ing ls1 to ls2 the first time the function is  
> called when ls1 is nil.
> The code here corrects the problem.
> This way of solving the problem using tail recursion and accumulators is  
> very Scheem'ish.
> Here is a more Lisp'ish solution.
>
> (defun pack (list)
>    (let (result-list sub-list)
>      (do ((current list (rest current))
>           (previous nil current))
>          ((null current)
>           (push sub-list result-list)
>           (nreverse result-list))
>        (when (and (not (eql (first current) (first previous))) (consp  
> sub-list))
>          (push sub-list result-list)
>          (setf sub-list nil))
>        (push (first current) sub-list))))
>
> Also note the use of eql rather than eq. This works for characters and  
> numbers as well and should be used instead.
> nreverse is more efficient than reverse and since you are cons'ing up a  
> new list anyhow safe.
>
> --------------
> John Thingstad

>>Mr John Thingstad

>I have a devil of a time understanding your code.

I'm so sorry to let you spend your time.

> The problem came from cons'ing ls1 to ls2 the first time the function is
> called when ls1 is nil.

Yes, now I understand.
Actually, I directly translated my code into Scheme, but it returned
error.
Therefore, evaluating (car '()) is clearly problem on Scheme; however
Common Lisp has a different attitude so that I did not see what is
wrong on my code.

>This way of solving the problem using tail recursion and accumulators
is very Scheem'ish.

Yes, now I slowly understand Schem'ish way is not always good.
Sometimes (and this is the time) I can not see anything clearly.

>Also note the use of eql rather than eq. This works for characters
and numbers as well and should be used instead.

Thanks for your advice.
Obviously, I made a mistake there. I should have used eql instead of
eq.

>nreverse is more efficient than reverse and since you are cons'ing up
a
> new list anyhow safe.

I see.
I have been very afraid of using "distructive" function(Is this so
called?).
But with efficiency, I try.

I really appreciate your help.
From: John Thingstad
Subject: Re: About Clisp
Date: 
Message-ID: <op.uc5hoamaut4oq5@pandora.alfanett.no>
P� Sun, 22 Jun 2008 14:14:19 +0200, skrev cametan  
<··············@gmail.com>:

>>> Mr John Thingstad
>
> >I have a devil of a time understanding your code.
>
> I'm so sorry to let you spend your time.
>

No problem it is mine to waste.

>> The problem came from cons'ing ls1 to ls2 the first time the function is
>> called when ls1 is nil.
>
> Yes, now I understand.
> Actually, I directly translated my code into Scheme, but it returned
> error.
> Therefore, evaluating (car '()) is clearly problem on Scheme; however
> Common Lisp has a different attitude so that I did not see what is
> wrong on my code.

Quite so. I had a similar problem programming Scheme.
Having (car nil) return nil is just a convenience as it gracefully accepts  
nil in a list without a need for a separate check which simplifies  
iteration code.

>
> nreverse is more efficient than reverse and since you are cons'ing up a
> new list anyhow safe.
>
> I see.
> I have been very afraid of using "distructive" function(Is this so  
> called?).
> But with efficiency, I try.
> I really appreciate your help.

Close enough. "Destructive". push, nreverse in combination is a common  
idiom in Lisp.
In combination it is always safe as the list produced by push is  
guarantied to be "fresh".
If in doubt it is better to avoid destructive functions.

--------------
John Thingstad