From: cametan on
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: Kojak on
Le Sun, 22 Jun 2008 00:47:24 -0700 (PDT),
cametan <Masashi.Kameda(a)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: Tayssir John Gabbour on
On Jun 22, 9:47 am, cametan <Masashi.Kam...(a)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 on
On Jun 22, 11:01 am, Tayssir John Gabbour
<tayssir.j...(a)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: Pascal J. Bourguignon on
cametan <Masashi.Kameda(a)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.