From: Tom
Subject: problems with recursion
Date: 
Message-ID: <9c9kjg$fiq$1@galaxy.uci.agh.edu.pl>
I had defined function which converts lists of lists into lists, without
repetition
of atoms, for example :

(A (B C) D) --> (A B C D) and so on. ( the order of atoms is not important )

The function's definition is :

(defun AAA (ZB)
     (setq wy '())
     (dolist (i ZB)
                (cond
                       ((atom i) (setq wy (cons i wy)))
                       ( t
                             (dolist (j (AAA i))
(*)
                                 (cond ( (not (member j wy)) (setq wy (cons
j wy) )))
                            )
                       )
              )
     )
 wy
)

Unfortunately, for (A (B C) D) I got (D C B) as if variable "wy" was common
for
all recursive callings to AAA( just like static variable in C ).
Is there any way to define "wy", so that it would be independent of  "wy"
from the previous invocation (in recursion chain). ------- (just like pure
local variable in C )

regerds,

tom

From: Johann Hibschman
Subject: Re: problems with recursion
Date: 
Message-ID: <260420011013457784%johannh@uclink.berkeley.edu>
In article <············@galaxy.uci.agh.edu.pl>, Tom
<·······@poczta.fm> wrote:

> Unfortunately, for (A (B C) D) I got (D C B) as if variable "wy" was common
> for
> all recursive callings to AAA( just like static variable in C ).
> Is there any way to define "wy", so that it would be independent of  "wy"
> from the previous invocation (in recursion chain). ------- (just like pure
> local variable in C )

Yes, it is.  Look up dynamic variables sometime.  In general, when you
want to introduce a new binding, use "let", as in

(defun aaa (zb)
  (let ((wy ()))
    (dolist ... )))
From: Frode Vatvedt Fjeld
Subject: Re: problems with recursion
Date: 
Message-ID: <2h8zkntowe.fsf@dslab7.cs.uit.no>
"Tom" <·······@poczta.fm> writes:

> (defun AAA (ZB)
>      (setq wy '())
>      (dolist (i ZB)
>                 (cond
>                        ((atom i) (setq wy (cons i wy)))
>                        ( t
>                              (dolist (j (AAA i))
> (*)
>                                  (cond ( (not (member j wy)) (setq wy (cons
> j wy) )))
>                             )
>                        )
>               )
>      )
>  wy
> )

First, "dangling parens" is not generally considered good style,
you'll probably find that proper formatting is very helpful for
readability:

  (defun aaa (zb)
    (setq wy ())
    (dolist (i zb)
      (cond
        ((atom i)
         (setq wy (cons i wy)))
        (t (dolist (j (AAA i))
             (cond
               ((not (member j wy))
                (setq wy (cons j wy))))))))
    wy)

Second, your variable named WY is here "free", meaning it is stored
somewhere "outside" the function. (Usually, for undeclared variables,
that "outside" will default to what can be described as a global
variable, but this is not really specified in the standard, and most
lisp implementations will warn you about this.) In lisp, variables are
not implicitly declared like you seem to expect by the form (setq wy ()).
Rather you must create a lexical binding (which can be thought of as
similar to C's dynamic stack variables), something like this:

  (defun aaa (zb)
    (let ((wy ()))
      (dolist (i zb)
        (cond
          ((atom i)
           (setq wy (cons i wy)))
          (t (dolist (j (aaa i))
               (cond
                 ((not (member j wy))
                  (setq wy (cons j wy))))))))
      wy))

..which will probably work the way you'd expect.

Now, lisp has IF, WHEN, and UNLESS which in some cases are more
suitable than COND:

  (defun aaa (zb)
    (let ((wy ()))
      (dolist (i zb)
        (if (atom i)
            (setq wy (cons i wy)))
          (dolist (j (aaa i))
            (unless (member j wy)
              (setq wy (cons j wy)))))
      wy))


..and PUSH which inserts an object at the "top" of a list:

  (defun aaa (zb)
    (let ((wy ()))
      (dolist (i zb)
        (if (atom i)
            (push i wy)
          (dolist (j (aaa i))
            (unless (member j wy)
              (push j wy)))))
      wy))

This, while perhaps not looking like the output of a seasoned lisper,
should be equivalent to your original function (modulo the binding),
only somewhat more readable.

-- 
Frode Vatvedt Fjeld