Frage

Ich versuche, die Ray-Tracing-Code Form Paul Grahams ANSI Common Lisp auf OS X SLIME mit OpenMCL (na ja, jetzt genannt CCL) zu laufen. In diesem Code, eine Konstante definierte es gibt, dessen Wert eine Struktur, und wenn ich entweder rufen schleim kompiliert-and-Load-Datei oder schleim kompiliert-defun auf jedem Funktion, die die konstante verwendet, erhalte ich eine Fehlermeldung:

  

Nein MAKE-LOAD-FORM Methode definiert   für #S (POINT: X 0                                                    : Y 0                                                    Z 200) [Bedingung des Typs   SIMPLE-ERROR]

Ich fand ein Post die Komplikation zu erklären und eine andere klagend, aber was muss, um den Code hinzugefügt wird diesen Aspekt OpenMCL zu verhandeln?

War es hilfreich?

Lösung

Wenn STRUKTUR-Objekte (und einige andere Arten von Objekten) erscheinen als wörtliche, konstante Objekte in Code von COMPILE-FILE verarbeitet werden, COMPILE-FILE muss wissen, wie das arrangieren, wenn die resultierende binäre Datei geladen wird, eine „Äquivalent“ Objekt wird erstellt. Es gibt viele möglichen Definitionen von „gleichwertig“: Manchmal ist es wichtig, dass die Komponenten der geladenen Objekts Aktienstruktur mit anderen Objekten, manchmal ist es wichtig, dass die Initialisierung in einer bestimmten Art und Weise geschieht, und manchmal keines dieser Dinge sind wichtig. Um zu bestimmen, wie das konstante Objekt zu erstellen, COMPILE-FILE ruft die generische Funktion MAKE-LOAD-FORM; Dieses Verhalten sollte in jedem CL Verweise oder ein Tutorial beschrieben. (Ein Verweis oder ein Tutorial sollte auch beachten, dass die Umsetzung nicht Standard-MAKE-LOAD-FORM Methoden definieren, die für alle Instanzen des Struktur-CLASS oder STANDARD-CLASS anwendbar wäre, und auch, dass MAKE-LOAD-FORM-SPAR beachten soll -SLOTS ist eine praktische Funktion in MAKE-LOAD-FORM Methoden für Objekte verwenden, deren Initialisierung muss nicht kompliziert sein, zum Beispiel:

(defmethod make-load-form ((p point) &optional env)
  (declare (ignore env))
  (make-load-form-saving-slots p))

Beachten Sie, dass das Verfahren zur Compile-Zeit definiert werden, so dass COMPILE-FILE es nennen kann, um zu bestimmen, wie das konstante Punktobjekt zu speichern.

Nichts davon ist CCL-spezifisch. Was könnte sein, ist die Frage, welche Dinge konstant sind, wörtliche Objekte und die Dinge nicht.

Code wie:

(defconstant a-point (make-point :x 0 :y 0 :z 200))

(defun return-a-point () a-point)

Der Compiler ist erlaubt (aber nicht erforderlich), um den Wert von A-POINT für den Verweis auf sie in der Funktion RETURN-A-POINT zu ersetzen. (Wenn der Compiler so tut, das wäre bedeuten, dass ein wörtliches / constant POINT Objekt im Code gibt es kompiliert wird, und COMPILE-Datei aufrufe müßte MAKE-LOAD-FORM, um zu bestimmen, wie das Objekt gespeichert werden soll und geladen; wenn die Compiler nicht diese Substitution nicht tun, dann MAKE-LOAD-FORM in diesem Beispiel nicht genannt werden muss.)

Ob eine Implementierung dieser Art von Substitution tut oder nicht, ist bis zur Umsetzung. Die Spezifikation läßt es auch nicht spezifiziert, ob die Wertform in einer defconstant Form zur Compile-Zeit ausgewertet wird, die Ladezeit oder beides, und stellt fest, dass Pflege (durch den Benutzer) ausgeübt werden muss, um sicherzustellen, dass der Ausdruck ergibt immer der gleiche Wert.

CCL versucht, im Allgemeinen die defconstant Wertform zur Compile-Zeit zu bewerten, und ist ziemlich aggressiv über die Werte benannter Konstanten für Verweise auf sie ersetzen; in einigen Fällen bedeutet dies, dass MAKE-LOAD-FORM Methoden auf den Klassen der Werte Konstanten definiert werden müssen. Andere Implementierungen können weniger bereit sein, für einige Arten von Objekten dieser Substitution zu tun. Beide Strategien sind richtig, und portablen Code kann nicht davon ausgehen, welche Strategien verfolgt werden (wenn auch viel vorgeblich portablen Code sicherlich nicht solche Annahmen getroffen werden.)

Eine unterschiedliche Behandlung der Dinge durch defconstant definiert scheint, wie die meist wahrscheinliche Ursache für diese Art der Sache (unerwartete Anrufe MAKE-LOAD-Form, die niemand die Mühe gemacht, zu definieren). Man kann einige dieser Probleme in einer Art und Weise vermeiden, indem tragbar sein sollte:

(defconstant a-point (make-point :x 0 :y 0 :z 200))

(defun return-a-point () (load-time-value (symbol-value 'a-point)))

Dies wird eine ähnliche Wirkung hat einfach eine Implementierung ermöglicht, die so tun will (wie CCL tut) mit konstanter Substitution zu tun, aber die Verwendung von LOAD-TIME-VALUE wird sichergestellt, dass der konstante Wert nur bei Belastung ausgewertet Zeit (und die MAKE-LOAD-FORM nicht beteiligt sein wird.)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top