> Tassilo Horn <
tassilo@member.fsf.org> writes:
>
>> Johan Andersson <
johan.rejeep@gmail.com> writes:
>>
>> Hi Johan,
>>
>>> Then I could easy update attributes on the objects, remove and add
>>> people and then update the file.
>>>
>>> I tried with a couple of solutions for this in Lisp:
>>>
>>> 1) One list named people:
>>> (
>>> (name age married sex)
>>> ...
>>> )
>>
>> I think a list of plists would be quite intuitive to someone with an OO
>> background. Here's a quick and dirty snippet which should get you
>> started:
>>
>> --8<---------------cut here---------------start------------->8---
>> (defvar persons
>> '((:name "Klaus" :age 36 :sex male)
>> (:name "Claudia" :age 31 :sex female)))
>> [...]
>> ;; Adjust the ages
>> (set-property "Klaus" :age 37)
>> (set-property "Claudia" :age 32)
Why not. The choice of internal representation doesn't matter. You
(require 'cl)
(defun make-keyword (name) (intern (format ":%s" name)))
(defmacro define-structure (name &rest fields)
`(progn
(defun* ,(intern (format "make-%s" name))
(&key ,@fields)
(list ',name ,@(mapcan (lambda (field)
(list (make-keyword (symbol-name field))
field)) fields)))
;; readers
,@(mapcar (lambda (field)
`(defun ,(intern (format "%s-%s" name field)) ; defstruct like naming.
(object)
(getf (cdr object) ,(make-keyword (symbol-name field))))) fields)
;; writers:
,@(mapcar (lambda (field)
`(defun ,(intern (format "set-%s-%s" name field)) (object value)
(assert (not (null object)))
(setf (getf (cdr object) ,(make-keyword (symbol-name field))) value)))
fields)
,@(mapcar (lambda (field)
`(defsetf ,(intern (format "%s-%s" name field))
,(intern (format "set-%s-%s" name field))))
fields)
',name))
(progn (pprint (macroexpand '(define-structure person name birthdate job))) nil)
-->
(progn
(defun* make-person (&key name birthdate job)
(list 'person :name name :birthdate birthdate :job job))
(defun person-name (object) (getf (cdr object) :name))
(defun person-birthdate (object) (getf (cdr object) :birthdate))
(defun person-job (object) (getf (cdr object) :job))
(defun set-person-name (object value)
(assert (not (null object)))
(setf (getf (cdr object) :name) value))
(defun set-person-birthdate (object value)
(assert (not (null object)))
(setf (getf (cdr object) :birthdate) value))
(defun set-person-job (object value)
(assert (not (null object)))
(setf (getf (cdr object) :job) value))
(defsetf person-name set-person-name)
(defsetf person-birthdate set-person-birthdate)
(defsetf person-job set-person-job)
'person)
(define-structure person name birthdate job)
--> person
(make-person :name "Tintin" :birthdate 1918 :job "Reporter")
--> (person :name "Tintin" :birthdate 1918 :job "Reporter")
(let ((tintin (make-person :name "Tintin" :birthdate 1918 :job "Reporter")))
(setf (person-birthdate tintin) 1920)
tintin)
--> (person :name "Tintin" :birthdate 1920 :job "Reporter")
(let ((tintin (make-person :name "Tintin" :birthdate 1918 :job "Reporter")))
(insert (format "%s is a %s\n" (person-name tintin) (person-job tintin))))
Tintin is a Reporter
Then, if you notice that p-list are too slow, or that you need
subclasses, you can easily substitute defstruct for define-structure,
and get structures with direct access slots, or if you notice that you
need multiple inheriting, you can substitute a defclass for the
define-structure, all with the rest of the program unchanged, since
using the functional abstraction defined by these accessors.
--
__Pascal Bourguignon__