Wie kann ich setf auf eine Struktur des Zugriffs tun, wenn intern verwendet
-
30-09-2019 - |
Frage
Ich möchte verschiedene Felder einer Struktur setf
auf eine bestimmte Variable abhängig. Ich beschloss, den folgenden Ansatz zu verwenden:
Erstellen Sie eine Zeichenkette mit dem Accessor Name Feld:
(setq my-string (format nil "STRUCT-ESTADISTICAS-NUM-~S" x))
und dann intern die Verwendung mit FUNCALL:
(funcall (intern my-string) *estadisticas*)
Dieser Aufruf gibt den richtigen Wert des Feldes Struktur, aber wenn ich setf
versuchen, diesen Wert zu ändern, es beschwert ich sagen:
(setf (funcall(intern my-string) *estadisticas*) 0)
Error: `(SETF FUNCALL)' is not fbound
kann ich verstehen, warum es nicht funktioniert, aber ich kann nicht einen Weg die Struktur der Felder finden zu ändern. Irgendeine Idee? Danke.
Lösung
Sie möchten über ihren Namen ein Schriftsteller Funktion der Struktur nennen, und der Name des Autors ist die Liste (setf accessor-name)
; so
(funcall (fdefinition (list 'setf (intern my-string))) 0 estadisticas)
Edit:
Nicht den Rest des Codes zu sehen, ist es schwer zu ergründen, was falsch gelaufen ist. Auf SBCL Dies funktioniert für mich:
(defstruct point x y)
(let ((point (make-point :x 1 :y 2)))
(funcall (fdefinition (list 'setf (intern "POINT-X"))) 10 point)
point)
Die oben auswertet zu
#S(POINT :X 10 :Y 2),
wie erwartet.
Andere Tipps
Motivation:
Strukturen sind eine relativ niedrige Ebene Möglichkeiten. ‚Speed‘ war ein wichtiges Entwicklungsziel. Indirection über Schreiber Funktionen nicht durch den Standard unterstützt (wie ich es gelesen). Heute Verwendung CLOS als Standard, es sei denn, man braucht eine bessere Effizienz der Strukturen (schneller lesen und Schreiben von Slots mit Strukturen sind manchmal möglich).
First - Stil:
Verwenden Sie INTERN nicht, verwenden FIND-SYMBOL. Geben Sie auch das Paket, sonst FIND-SYMBOL den Laufzeitwert von * Paket * als Paket verwenden
Second - DEFSTRUCT
Wenn ich die ANSI CL Standard richtig gelesen, ist es nicht, dass DEFSTRUCT schafft Schreiber Funktionen für Slots wie DEFCLASS tut.
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)).
So konstruieren einen solchen Namen (SETF FOO-BAR) und versuchen, eine Funktion zu finden, dass fehlschlagen, da eine solche Funktion gibt es keine von der DEFSTRUCT definiert.
Das in Benutzercode (setf (foo-bar some-Struktur) 42) arbeitet, basiert auf definierten SETF Erweiterungen von DEFSTRUCT vorgesehen, aber nicht auf definierten SETF Accessorfunktionen.
Einige Schriftsteller bieten Common Lisp-Implementierungen können Funktionen als Nicht-Standard-Erweiterung zu ANSI CL.
Mögliche Lösungen :
eine Verwendung CLOS Klassen), DEFCLASS tut, was Sie wollen
b) schreiben die Verfasser Funktionen selbst
(defun (setf foo-bar) (new-value struct)
(setf (foo-bar struct) new-value))
(funcall (fdefinition '(setf foo-bar)) 300 *foo*)
Vor funktioniert dann.
c) (SETF SCHLITZ-VALUE) -. Ein anderes Nicht-Standard-Feature von einigen Implementierungen
Bei einigen Implementierungen von Common Lisp das funktioniert nicht nur für CLOS Klassen, sondern auch für die Strukturen:
(setf (slot-value some-struct 'bar) 42)
Ich bin mir nicht sicher, ob Allegro CL unterstützt, die, aber das wäre leicht herausfinden.