Come posso fare setf su funzioni di accesso di una struttura quando si utilizza stagista

StackOverflow https://stackoverflow.com/questions/3641509

  •  30-09-2019
  •  | 
  •  

Domanda

Mi piacerebbe setf diversi campi di una struct a seconda di una certa variabile. Ho deciso di utilizzare il seguente approccio:

generare una stringa con il nome di accesso del campo:

(setq my-string (format nil "STRUCT-ESTADISTICAS-NUM-~S" x))

e quindi utilizzare stagista con funcall:

(funcall (intern my-string) *estadisticas*)

Questa chiamata restituisce il valore corretto del campo del struct, ma se provo setf per modificare questo valore si lamenta dicendo:

(setf (funcall(intern my-string) *estadisticas*) 0)
Error: `(SETF FUNCALL)' is not fbound

posso capire perché non funziona, ma non riesco a trovare un modo per modificare i campi della struct. Qualche idea? Grazie.

È stato utile?

Soluzione

Si desidera chiamare una funzione scrittore del struct attraverso il suo nome, e il nome dello scrittore è la lista (setf accessor-name); così

(funcall (fdefinition (list 'setf (intern my-string))) 0 estadisticas)

Modifica:

Non vedendo il resto del codice, è difficile capire cosa è andato storto. Su SBCL Questo funziona per me:

(defstruct point x y)
(let ((point (make-point :x 1 :y 2)))
  (funcall (fdefinition (list 'setf (intern "POINT-X"))) 10 point)
  point)

I Esamina sopra per

#S(POINT :X 10 :Y 2),

come previsto.

Altri suggerimenti

Motivazione:

Le strutture sono una struttura relativamente di basso livello. 'Speed' è stato un importante obiettivo di progettazione. Indirection tramite funzioni scrittore non è supportato dallo standard (come ho letto). Oggi, l'uso CLOS come default, a meno che uno ha bisogno di una migliore efficienza delle strutture (velocità di lettura e scrittura di slot con le strutture sono a volte possibile).

In primo luogo - stile:

Non utilizzare INTERN, utilizzare la funzione Trova-SIMBOLO. Inoltre, specificare il pacchetto, altrimenti TROVA-SIMBOLO utilizzerà il valore di runtime del pacchetto * * come il pacchetto

In secondo luogo - defstruct

Se ho letto bene lo standard ANSI CL, non è che defstruct crea funzioni scrittore per gli slot come DEFCLASS fa.

CL-USER 24 > (defstruct foo bar baz)
FOO

CL-USER 25 > #'(setf foo-bar)

Error: Undefined function (SETF FOO-BAR) in form (FUNCTION (SETF FOO-BAR)).

Quindi, la costruzione di un tale nome (SETF FOO-bar) e cercando di trovare una funzione per quel avrà esito negativo, dal momento che non esiste una funzione definita dal defstruct.

Che in codice utente (setf (foo-bar some-struct) 42) funziona, si riferiscono al espansioni SETF definiti fornite da defstruct, ma non su SETF definito funzione di accesso funzioni.

Alcune implementazioni Common Lisp può fornire funzioni scrittore come estensione non standard ANSI CL.

possibili soluzioni :

a) classi di uso CLOS, DEFCLASS fa quello che vuoi

b) scrivere le funzioni scrittore te

(defun (setf foo-bar) (new-value struct)
   (setf (foo-bar struct) new-value))

Ora:

(funcall (fdefinition '(setf foo-bar)) 300 *foo*)

Sopra quindi funziona.

c) (SETF SLOT-VALUE) -. Un'altra caratteristica non standard di alcune implementazioni

In alcune implementazioni di Common Lisp questo funziona non solo per le classi CLOS, ma anche per le strutture:

(setf (slot-value some-struct 'bar) 42)

Io non sono sicuro se Allegro CL fa supporto che, ma che sarebbe stato facile scoprire.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top