From: John Hinsdale
Subject: Initializing an array of structures in Lisp?
Date: 
Message-ID: <a7836965.0408180937.75decc97@posting.google.com>
Hi all I have what looks like a basic question but I cannot seem to
find the answer by Googling the Web or Usenet.

I want to initialize an array of structures with some static data
at the beginning of my program and the add some stuff to it later.

Below is the smallest nontrival example that illustrates the
way I'm doing it now ... this business with using "elt"
strikes me as ugly and my little "there must be a better way"
light is lighting up.  Any advice?

My real structure has about eight elements and has about a dozen
initial instances in the array.  (It's metadata for an external
API/library I'm interfacing with).

;;; EXAMPLE ....

(defstruct stooge
  first-name last-name quotation)

(defvar *initialdata*
   ;  First    Last       Quote
   ; --------  --------   -----------------------------
  '(("Moe"     "Howard"   "Spread oooouuuut!")
    ("Larry"   "Fine"     "Why you ... I oughtta")
    ("Curly"   "Howard"   "Moe!  Larry!  The Cheese! Woohoowoo!")))

(setf stooges (make-array 3 :adjustable t :fill-pointer 0))

; Init to the first three
(mapcar #'(lambda (l)
            (vector-push (make-stooge ; *** THIS IS UGLY? ***
                          :first-name (elt l 0)
                          :last-name (elt l 1)
                          :quotation (elt l 2))
                         stooges))
        *initialdata*)

(print stooges)

; ... later on in the program
(vector-push-extend (make-stooge :first-name "Shemp"
                                 :last-name "Howard"
                                 :quotation "I'm not like Curly")
                    stooges)

(print stooges)

---
John Hinsdale, Alma Mater Software, Inc., Tarrytown, NY 10591-3710 USA
···@alma.com | http://www.alma.com/staff/hin | +1 914 631 4690

From: Frank Buss
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <cg05ph$t14$1@newsreader2.netcologne.de>
···@alma.com (John Hinsdale) wrote:

> I want to initialize an array of structures with some static data
> at the beginning of my program and the add some stuff to it later.

why not using a list?

There is a reader macro for structures:

http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/sec_2-4-8-13.html 

and with lists it looks like this:

(defstruct test f1 f2 f3)
(setf records
      '(#s(test :f1 1 :f2 2 :f3 3)
        #s(test :f1 4 :f2 5 :f3 6)))
(setf records (append records '(#s(test :f1 7 :f2 8 :f3 9))))
(test-f3 (car records))

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Christophe Rhodes
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <sq4qn0co3j.fsf@cam.ac.uk>
···@alma.com (John Hinsdale) writes:

> ;;; EXAMPLE ....
>
> (defstruct stooge
>   first-name last-name quotation)

(defstruct (stooge 
            (:constructor make-stooge) 
            (:constructor boa-make-stooge (first-name last-name quotation)))
  first-name last-name quotation)

> (defvar *initialdata*
>    ;  First    Last       Quote
>    ; --------  --------   -----------------------------
>   '(("Moe"     "Howard"   "Spread oooouuuut!")
>     ("Larry"   "Fine"     "Why you ... I oughtta")
>     ("Curly"   "Howard"   "Moe!  Larry!  The Cheese! Woohoowoo!")))

This is fine, though it makes the initialization of stooges slightly
more cumbersome than it could be if it were instead lists of slots:
 '(("Moe" "Larry" "Curly")
   ("Howard" "Fine" "Howard")
   ...)

You could alternatively avoid the need for the boa constructor if you
defined this initialization list a bit more like a table:
 '((:first-name "Moe" :last-name "Howard" :quotation "Spread oooouuuut!")
   ...)

> (setf stooges (make-array 3 :adjustable t :fill-pointer 0))
>
> ; Init to the first three
> (mapcar #'(lambda (l)
>             (vector-push (make-stooge ; *** THIS IS UGLY? ***
>                           :first-name (elt l 0)
>                           :last-name (elt l 1)
>                           :quotation (elt l 2))
>                          stooges))
>         *initialdata*)

(defvar stooges)
(setf stooges 
      (make-array 3 :adjustable t :fill-pointer 3
                    :initial-contents (loop for i in *initialdata*
                                        collect (apply #'boa-make-stooge i))))

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Vassil Nikolov
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <lzr7q3hlbk.fsf@janus.vassil.nikolov.names>
Christophe Rhodes <·····@cam.ac.uk> writes:

> ···@alma.com (John Hinsdale) writes:
>
>> ;;; EXAMPLE ....
>>
>> (defstruct stooge
>>   first-name last-name quotation)
>
> (defstruct (stooge 
>             (:constructor make-stooge) 
>             (:constructor boa-make-stooge (first-name last-name quotation)))
>   first-name last-name quotation)
>
>> (defvar *initialdata*
>>    ;  First    Last       Quote
>>    ; --------  --------   -----------------------------
>>   '(("Moe"     "Howard"   "Spread oooouuuut!")
>>     ("Larry"   "Fine"     "Why you ... I oughtta")
>>     ("Curly"   "Howard"   "Moe!  Larry!  The Cheese! Woohoowoo!")))
>
> This is fine, though it makes the initialization of stooges slightly
> more cumbersome than it could be if it were instead lists of slots:
>  '(("Moe" "Larry" "Curly")
>    ("Howard" "Fine" "Howard")
>    ...)


  However, with this structure, adding/changing/removing an element
  will involve modifying _all_ lines of the file, making the delta
  noisier.


> [...]
>> (setf stooges (make-array 3 :adjustable t :fill-pointer 0))
>>
>> ; Init to the first three
>> (mapcar #'(lambda (l)
>>             (vector-push (make-stooge ; *** THIS IS UGLY? ***
>>                           :first-name (elt l 0)
>>                           :last-name (elt l 1)
>>                           :quotation (elt l 2))
>>                          stooges))
>>         *initialdata*)
>
> (defvar stooges)
> (setf stooges 
>       (make-array 3 :adjustable t :fill-pointer 3
>                     :initial-contents (loop for i in *initialdata*
>                                         collect (apply #'boa-make-stooge i))))


  Why not simply (mapcar #'boa-make-stooge *initialdata*) for the
  initial contents?

  ---Vassil.

-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Vassil Nikolov
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <lzn00rhkth.fsf@janus.vassil.nikolov.names>
Vassil Nikolov <········@poboxes.com> writes:

> Christophe Rhodes <·····@cam.ac.uk> writes:
> [...]
>>> (setf stooges (make-array 3 :adjustable t :fill-pointer 0))
>>>
>>> ; Init to the first three
>>> (mapcar #'(lambda (l)
>>>             (vector-push (make-stooge ; *** THIS IS UGLY? ***
>>>                           :first-name (elt l 0)
>>>                           :last-name (elt l 1)
>>>                           :quotation (elt l 2))
>>>                          stooges))
>>>         *initialdata*)
>>
>> (defvar stooges)
>> (setf stooges 
>>       (make-array 3 :adjustable t :fill-pointer 3
>>                     :initial-contents (loop for i in *initialdata*
>>                                         collect (apply #'boa-make-stooge i))))
>
>
>   Why not simply (mapcar #'boa-make-stooge *initialdata*) for the
>   initial contents?


  That was wrong---should be

    (mapcar #'(lambda (i) (apply #'boa-make-stooge i)) *initialdata*)

  Sorry.  Not much simpler (though more in functional style).

  ---Vassil.

-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: John Hinsdale
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <a7836965.0408191253.73161f5c@posting.google.com>
>   That was wrong---should be
> 
>     (mapcar #'(lambda (i) (apply #'boa-make-stooge i)) *initialdata*)
> 

I ended up using the "boa-constructor" suggested by Christophe
Rhodes, and applied across my initial array with MAPCAR as
suggested by Vassil Nikolov.  This lets me hardcode the initial
data in the "natural" way I wanted to, "record-wise"
(I could have transposed it
and stored it 'slotwise" but that is less natural for me and is
as was pointed out slightly harder to maintain).

I did not need to use DESTRUCTURING-BIND but it turns out that
will be useful to me elsewhere in unrlated issue (thanks for that too).

see I knew there had to be a better way ;)

---
John Hinsdale, Alma Mater Software, Inc., Tarrytown, NY 10591-3710 USA
From: Christophe Rhodes
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <sq3c2jbjqr.fsf@cam.ac.uk>
Vassil Nikolov <········@poboxes.com> writes:

>   Why not simply (mapcar #'boa-make-stooge *initialdata*) for the
>   initial contents?

> Christophe Rhodes <·····@cam.ac.uk> writes:
>>  '(("Moe" "Larry" "Curly")
>>    ("Howard" "Fine" "Howard")
>>    ...)
>
>   However, with this structure, adding/changing/removing an element
>   will involve modifying _all_ lines of the file, making the delta
>   noisier.

This is why.

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Marco Baringer
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <m23c2ke1yf.fsf@convey.it>
···@alma.com (John Hinsdale) writes:

> ;;; EXAMPLE ....
>
> (defstruct stooge
>   first-name last-name quotation)
>
> (defvar *initialdata*
>    ;  First    Last       Quote
>    ; --------  --------   -----------------------------
>   '(("Moe"     "Howard"   "Spread oooouuuut!")
>     ("Larry"   "Fine"     "Why you ... I oughtta")
>     ("Curly"   "Howard"   "Moe!  Larry!  The Cheese! Woohoowoo!")))

option 1:

(setf stooges
      (mapcar (lambda (spec)
                (destructuring-bind (first-name last-name quote)
                  (make-stooge :first-name first-name
                               :last-name last-name 
                               :quotation quote)))
              *initialdata*))

option 2 (if you want to maintain the visual formatting of the data):

(defstruct (stooge (:constructor make-stooge)
                   (:constructor make-stooge* 
                    first-name last-name quotation))
  first-name
  last-name
  quotation)

(defvar *stooges*
        (make-array 3 :adjustable t :fill-pointer 0
                    :initial-contents (list
;;            first   last     quotation
(make-stooge* "Moe"   "Howard" "Spread oooouuuut!")
(make-stooge* "Larry" "Fine"   "Why you ... I oughtta")
(make-stooge* "Curly" "Howard" "Moe!  Larry!  The Cheese! Woohoowoo!"))))



look up destructuring-bind and boa (By-Order-of-Arguments) struct constructors.

-- 
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
     -Leonard Cohen
From: Tayssir John Gabbour
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <866764be.0408190120.45c302b5@posting.google.com>
···@alma.com (John Hinsdale) wrote in message news:<····························@posting.google.com>...
> Hi all I have what looks like a basic question but I cannot seem to
> find the answer by Googling the Web or Usenet.
> 
> I want to initialize an array of structures with some static data
> at the beginning of my program and the add some stuff to it later.

You did already initialize structs with *initialdata*; you simply need
your STOOGE structure to read and write structures using lists instead
of the default datatype.

At the interactive prompt, assuming *initialdata* is already defined:

;; note the (:type list) part
CL-USER> (defstruct (stooge (:type list))
           first-name last-name quotation)
stooge


CL-USER> (mapcar #'stooge-first-name *initialdata*)
("Moe" "Larry" "Curly")


CL-USER> (mapcar #'stooge-last-name *initialdata*)
("Howard" "Fine" "Howard")


CL-USER> (mapcar #'stooge-quotation *initialdata*)
("Spread oooouuuut!" "Why you ... I oughtta"
 "Moe!  Larry!  The Cheese! Woohoowoo!")


CL-USER> (make-stooge :first-name "Shemp"
                      :last-name "Howard"
                      :quotation "I'm not like Curly")
("Shemp" "Howard" "I'm not like Curly")


Now, I don't use structures often, so I hope someone corrects me if
I'm misunderstanding the issue.


MfG,
Tayssir
From: apelsp853
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <4ab4b8d6.0408191247.30399064@posting.google.com>
···@alma.com (John Hinsdale) wrote in message news:<····························@posting.google.com>...
> Hi all I have what looks like a basic question but I cannot seem to
> find the answer by Googling the Web or Usenet.
> 
> I want to initialize an array of structures with some static data
> at the beginning of my program and the add some stuff to it later.
> 
> Below is the smallest nontrival example that illustrates the
> way I'm doing it now ... this business with using "elt"
> strikes me as ugly and my little "there must be a better way"
> light is lighting up.  Any advice?
> 

Hi, I am relatively new to Lisp, so take this advice lightly.

You can define your own constructors for structures (see: By-Position
Constructor Functions in CLtL2). Using this idea, your example can be
written as:

(defstruct (stooge
	    (:constructor make-stooge-positional (first-name last-name
quotation)))
  first-name last-name quotation)

(defvar *initialdata*
   ;  First    Last       Quote
   ; --------  --------   -----------------------------
  '(("Moe"     "Howard"   "Spread oooouuuut!")
    ("Larry"   "Fine"     "Why you ... I oughtta")
    ("Curly"   "Howard"   "Moe!  Larry!  The Cheese! Woohoowoo!")))

(setf stooges (make-array 3
			  :initial-contents (mapcar #'(lambda (flds) (apply
#'make-stooge-positional flds)) *initialdata*)
			  :adjustable t
			  :fill-pointer 3))

(print stooges)

Regards,
apelsp853
From: Christophe Turle
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <cg2fnv$aq5$1@amma.irisa.fr>
> I want to initialize an array of structures with some static data
> at the beginning of my program and the add some stuff to it later.
> 
> Below is the smallest nontrival example that illustrates the
> way I'm doing it now ... this business with using "elt"
> strikes me as ugly and my little "there must be a better way"
> light is lighting up.  Any advice?
> 
> My real structure has about eight elements and has about a dozen
> initial instances in the array.  (It's metadata for an external
> API/library I'm interfacing with).
> 
> ;;; EXAMPLE ....
> 
> (defstruct stooge
>   first-name last-name quotation)
> 
> (defvar *initialdata*
>    ;  First    Last       Quote
>    ; --------  --------   -----------------------------
>   '(("Moe"     "Howard"   "Spread oooouuuut!")
>     ("Larry"   "Fine"     "Why you ... I oughtta")
>     ("Curly"   "Howard"   "Moe!  Larry!  The Cheese! Woohoowoo!")))
> 
> (setf stooges (make-array 3 :adjustable t :fill-pointer 0))
> 
> ; Init to the first three
> (mapcar #'(lambda (l)
>             (vector-push (make-stooge ; *** THIS IS UGLY? ***
>                           :first-name (elt l 0)
>                           :last-name (elt l 1)
>                           :quotation (elt l 2))
>                          stooges))
>         *initialdata*)

(loop for (first-name last-name quotation) in *initialdata*
      do (vector-push (make-stooge :first-name first-name
				   :last-name  last-name
				   :quotation  quotation )
		      stooges ))


ctu.
From: Pascal Bourguignon
Subject: Re: Initializing an array of structures in Lisp?
Date: 
Message-ID: <87brh75dy4.fsf@thalassa.informatimago.com>
Christophe Turle <······@nospam.fr> writes:

> > I want to initialize an array of structures with some static data
> > at the beginning of my program and the add some stuff to it later.
> > Below is the smallest nontrival example that illustrates the
> > way I'm doing it now ... this business with using "elt"
> > strikes me as ugly and my little "there must be a better way"
> > light is lighting up.  Any advice?
> > My real structure has about eight elements and has about a dozen
> > initial instances in the array.  (It's metadata for an external
> > API/library I'm interfacing with).
> > ;;; EXAMPLE ....
> > (defstruct stooge
> >   first-name last-name quotation)
> > (defvar *initialdata*
> >    ;  First    Last       Quote
> >    ; --------  --------   -----------------------------
> >   '(("Moe"     "Howard"   "Spread oooouuuut!")
> >     ("Larry"   "Fine"     "Why you ... I oughtta")
> >     ("Curly"   "Howard"   "Moe!  Larry!  The Cheese! Woohoowoo!")))
> > (setf stooges (make-array 3 :adjustable t :fill-pointer 0))
> > ; Init to the first three
> > (mapcar #'(lambda (l)
> >             (vector-push (make-stooge ; *** THIS IS UGLY? ***
> >                           :first-name (elt l 0)
> >                           :last-name (elt l 1)
> >                           :quotation (elt l 2))
> >                          stooges))
> >         *initialdata*)
>
> (loop for (first-name last-name quotation) in *initialdata*
>       do (vector-push (make-stooge :first-name first-name
> 				   :last-name  last-name
> 				   :quotation  quotation )
> 		      stooges ))
 
(defparameter stooges
    (map 'vector (lambda (rec) (make-stooge :first-name (first rec)
                                            :last-name  (second rec)
                                            :quotation  (third rec))) 
                 *initialdata*))


It could be even simplier with:

(defstruct (stooge (:type list)) first-name last-name quotation)

(defparameter stooges
    (make-array (list (length *initialdata*)) :initial-contents *initialdata*))


Note that it depends on the number of fields. For a large number, I'd do:

(defparameter stooges
  (map 'vector (lambda (rec) 
                 (apply (function make-stooge)
                        (mapcan (lambda (field value) (list field value))
                                '(:first-name :last-name  :quotation ...)
                                rec)))
                *initialdata*))


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

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.