Subject: Re: SETF and variable issues in Self Similar program.
From: rpw3@rpw3.org (Rob Warnock)
Date: Fri, 07 Dec 2007 00:07:38 -0600
Newsgroups: comp.lang.lisp
Message-ID: <2cSdnZXVfd63fsXanZ2dnUVZ_oGjnZ2d@speakeasy.net>
Rainer Joswig  <joswig@lisp.de> wrote:
+---------------
| Eric <ericbelcastro@gmail.com> wrote:
| > Because any number of ratios may be input, I am automatically creating
| > variables and assigning names to them.  I am doing it like this...
...
| > Also - are there simple ways of automatically creating incremented
| > variable names?  I tried intern on strings but that didn't work too
| > well, and settled on my current method.
| 
| (defparameter *my-symbol-counter* 0)
| (defun make-symbol-plus-counter (&optional (name "FOO")
|                                            (package *package*)
|                                            (counter '*my-symbol-counter*))
|   (prog1 (intern (concatenate 'string
|                               name
|                               (princ-to-string (symbol-value counter)))
|                  package)
|     (incf (symbol-value counter))))
+---------------

You showed him how to do it, but you forgot to tell him *NOT TO*!!  ;-}

That's right, Eric, *don't* do this. Instead, define yourself *one*
global variable that hold either an adjustable array or a hash table
(or some kind of tree structure, whatever) that can be grown dynamically
and be quickly indexed by your "counter" numbers, e.g.:

    > (defvar *lists* (make-array 20 :adjustable t :fill-pointer 0))

    *lists*
    > (defun add-new-list (list)
	(vector-push-extend list *lists*
			    ;; exponential growth [Fibonacci might be better]
			    (array-dimension *lists* 0)))

    ADD-NEW-LIST
    > (add-new-list '(a a b a))

    0
    > (add-new-list '(c d c d e e))

    1
    > (add-new-list '(f g h))

    2
    > (length *lists*)

    3
    > *lists*

    #((A A B A) (C D C D E E) (F G H))
    > (aref *lists* 1)                   ; fast access to any one

    (C D C D E E)
    > (map 'list #'length *lists*)       ; can use sequence functions

    (4 6 3)
    > (apply #'lcm *)

    12
    > 

That is, having inserted a number of lists of varying lengths,
it's rather simple to "mine" the data and find out, say, the
least common multiple of their lengths [which is sometimes
something you might want to know about a series of patterns].

Let's add 100 more lists, and see what happens:

    > (loop for i below 200 by 2 do
	(add-new-list (list i (1+ i)) ))

    NIL
    > (length *lists*)                  ; the "active" length (fill pointer)

    103
    > (array-dimension *lists* 0)       ; the total length

    160
    > (let ((*print-length* 8))
	(print *lists*)
	nil)

    #((A A B A) (C D C D E E) (F G H) (0 1) (2 3) (4 5) (6 7) (8 9) ...) 
    NIL
    > (aref *lists* 97)                 ; fast access to any one

    (188 189)
    >

The array has only been resized three times (doubling each time),
so the number of resizings per insertion can be made as small as
you like.


-Rob

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