[elephant-devel] using association slots

Ian Eslick eslick at media.mit.edu
Tue Jun 17 21:31:36 UTC 2008


On Jun 17, 2008, at 3:23 PM, LukasGiessmann wrote:

> hello,
>
> just in case you're wondering why i'm coming up with questions  
> concerning
> marc's topic "associations in the elephant system", i'm trying to  
> assist
> him with this topic, so there might be several questions coming up  
> in the
> next time - hope you don't mind.
> to get straight to the point:
>
> 1)
> i tried to work with the last person/job example and the new  
> association
> slots, so i made the following example:

I apologize for not documenting or providing better examples for the  
final association design. Hopefully this will help in the meantime.

> ---
> (defpclass job()
>  ((title :initarg :title :accessor title-of :index t)
>   (company :initarg :company :accessor company-of :index t)))
>

(defpclass job()
  ((title :initarg :title :accessor title-of :index t)
   (company :initarg :company :accessor company-of :index t)
   (people :accessor job-holders :associate (person job))))

Associations are restricted to mappings between classes.  Here we  
indicate that a virtual slot people (accessor is job-holders) is  
associated with all objects of class 'person that contain this  
instances in slot 'job.

> (defpclass person()
>  ((name :initarg :name :accessor name-of :index t)
>   (job :initarg :job :accessor job-of :associate t)))
>
(defpclass person()
  ((name :initarg :name :accessor name-of :index t)
   (job :initarg :job :accessor job-of :associate job)))

Providing :associate job tells the person class that the slot 'job  
contains instances of type job and to maintain an association to job  
instances (each person has 1 job, each job may have many people).

The initarg for job here requires a patch that I'll submit shortly.

>
> (defvar *max-persons* 500)
> (defvar *max-jobs* 100)
>
> (defun make-instances ()
>  (with-transaction ()
>    (dotimes (i *max-jobs*)
>      (let ((current-job (make-instance 'job :title (string (gensym))
> :company (string (gensym)))))
> 	(dotimes (j (/ *max-persons* *max-jobs*))
> 	  (make-instance 'person :name (string (gensym)) :job current- 
> job))))))
> ---
>
> after the call of make-instances there are 100 jobs and for every job
> there exist 5 persons.
> but i have still the following problem:
> how can i get all persons which associate a certain job by using the
> instance of the job which should be associated by the persons.
> i thought on something like:
>
> ---
> (defvar *obj* (first (get-instances-by-class 'job)))
> (get-instance-by-value 'person 'job *obj*)
> ---

(job-holders *obj*) => < list of five people >

(setf (job-holders *obj*) (sixth (get-instances-by-class 'person)))
(job-holders *obj*) => < list of six people >

I made two small enhancements while exploring this example which I  
will checkin shortly:

1) Can treat a slot associated with another class as an indexed slot:
    (get-instances-by-value 'person 'job *obj*)

2) Now allows :initargs to set the slot value for association slots that
    contain a single object.  (I may allow this for other types later)

>
> 2)
> what is the better way for using association slots in your opinion,
> the one of the example above or a special class which contains only
> associations of jobs and persons?


> ---
> (defpclass p-j-assoc()
>  ((job :initarg :job :accessor job-of :associate t)
>   (person :initarg :person :accessor person-of :associate t)))
> ---
>
> 3)
> how do i work with many-to-many association slots, since it is not
> possible for me to assign a value to the slot.

This is what associations are an effective shorthand for; so you don't  
have to create an explicit object.

(defpclass job()
  ((title :initarg :title :accessor title-of :index t)
   (company :initarg :company :accessor company-of :index t)
   (people :accessor job-holders :associate (person job) :many-to-many  
t)))

(defpclass person()
  ((name :initarg :name :accessor name-of :index t)
   (jobs :accessor jobs-of :associate (job people) :many-to-many t))

This defines a many-to-many relationship between job and person.   
Unfortunately currently initargs don't work here.  You can add  
elements by (setf (jobs-of joe) janitor) and get access to all  
associated elements via (job-holders janitor) => joe.

I need to add insert/delete operations (there are stubs in  
association.lisp) so you can work with the association more directly.   
I also fixed a bug or two as well.  I'll let you know when I've  
checked in the fixes.  Thanks for prompting the exercise!

>
> thank you in advance.
>
>
> best regards
>
> lukas
>
> _______________________________________________
> elephant-devel site list
> elephant-devel at common-lisp.net
> http://common-lisp.net/mailman/listinfo/elephant-devel




More information about the elephant-devel mailing list