In Common Lisp, le strutture sono considerate record rigidi e di basso livello. Non hanno caratteristiche dinamiche fantasiose.
Quello che si può fare con le strutture è definire un nuovo tipo di struttura che eredita da un altro. È disponibile un'eredità singola.
Per gestire l'estensibilità dinamica, un modo tipico è aggiungere uno slot di elenco di proprietà a una struttura. Vedi la risposta di Giosuè.
Quindi esiste il Common Lisp Object System, che fornisce ereditarietà multipla e che è possibile modificare le classi in fase di runtime. Quindi puoi aggiungere uno slot ad una classe e le istanze di quell'aggiornamento di classe. Puoi anche modificare la classe di un oggetto e gli slot possono essere aggiunti o eliminati. Tuttavia, in genere tutte le istanze di una classe avranno lo stesso set di slot. Di nuovo, si vede che uno slot con un elenco di proprietà può essere aggiunto e utilizzato per l'estensibilità.
Esistono altri sistemi di oggetti per Common Lisp, che possono facilmente aggiungere slot su una base peristanza. Ma di solito è troppo per usarli solo per quello, dal momento che sono un po 'più potenti.
Con CLOS e il protocollo Meta-oggetto si può provare a nasconderlo.Qui sto usando LispWorks:
Definiamo una classe intermedia per le nostre proprietà:
(defclass property-mixin()
((plist :initform nil))
#+lispworks
(:optimize-slot-access nil))
impostazione e di lettura delle proprietà:
(defmethod set-property ((object property-mixin) key value)
(setf (getf (slot-value object 'plist) key) value))
(defmethod get-property ((object property-mixin) key)
(getf (slot-value object 'plist) key))
Ora dobbiamo scrivere i metodi per rendere SLOT-VALUE
accettare i nostri nomi di proprietà :
(defmethod (setf clos:slot-value-using-class)
(value (class standard-class) (object property-mixin) slot-name)
(declare (ignorable class))
(if (slot-exists-p object slot-name)
(call-next-method)
(progn
(set-property object slot-name value)
value)))
(defmethod clos:slot-value-using-class ((class standard-class)
(object property-mixin)
slot-name)
(declare (ignorable class))
(if (slot-exists-p object slot-name)
(call-next-method)
(get-property object slot-name)))
Esempio. Si definisce una classe di automobili con due slot:
(defclass automobile (property-mixin)
((company :initarg :company)
(motor :initarg :motor))
#+lispworks
(:optimize-slot-access nil))
ora un'istanza:
CL-USER 45 > (setf a6 (make-instance 'automobile :company :audi :motor :v6))
#<AUTOMOBILE 402005B47B>
Siamo in grado di ottenere un normale valore di slot:
CL-USER 46 > (slot-value c1 'motor)
:V6
Scriviamo ad uno slot che non lo fa esiste, ma sarà aggiunto alla nostra lista di proprietà:
CL-USER 47 > (setf (slot-value a6 'seats) 4)
4
Possiamo ottenere il valore indietro:
CL-USER 48 > (slot-value c1 'seats)
4
Grazie, questo è quasi esattamente quello che sto cercando. Ma c'è un modo per avere l'elenco delle proprietà, come lo metti, come solo altri slot nel 'nodo'? In altre parole, c'è un modo per fare '(make-node 'some-label: one 1: two 2) => (SOME-LABEL: ONE 1: TWO 2)', invece di '(SOME-LABEL (: ONE 1: TWO 2)) '? –
In breve, no. [La risposta di Rainer] (http://stackoverflow.com/a/17556349/1281433) approfondisce le strutture in generale, ma il punto è che le strutture hanno un numero fisso di slot. Anche se puoi usare 'defstruct' per creare" record di poveri "con l'opzione' (: type list) ', hai ancora solo un numero fisso di slot (il che significa che l'elenco ha un numero fisso di elementi). Sembra davvero che tu voglia solo una lista di proprietà. –
Sì, leggendo la risposta di Rainer, penso che ci sia più potenza di fuoco di quanto ho bisogno per quello che sto facendo. Grazie per il consiglio, ragazzi! –