Domanda

Sto cercando di eseguire il codice di ray tracing dal ANSI Common Lisp di Paul Graham su OS X usando SLIME con OpenMCL (bene, ora chiamato CCL). In quel codice, c'è una costante definita il cui valore è una struttura e quando chiamo file-compila-e-carica-melma o -compilazione-defun di melma su qualsiasi funzione che utilizza la costante, viene visualizzato un messaggio di errore:

  

Non è stato definito alcun metodo MAKE-LOAD-FORM   per #S (PUNTO: X 0                                                    : Y 0                                                    : Z 200) [Condizione del tipo   SEMPLICE-ERRORE]

Ho trovato un post che spiega la complicazione e un altro lamentandolo, ma cosa deve essere aggiunto al codice per negoziare questo aspetto di OpenMCL?

È stato utile?

Soluzione

Quando STRUCTURE-OBJECTs (e alcuni altri tipi di oggetti) appaiono come oggetti letterali e costanti nel codice elaborati da COMPILE-FILE, COMPILE-FILE deve sapere come organizzare che, quando viene caricato il file binario risultante, un " equivalente " l'oggetto è stato creato. Esistono molte definizioni possibili di "equivalente". : a volte, è importante che i componenti dell'oggetto caricato condividano la struttura con altri oggetti, a volte è importante che l'inizializzazione avvenga in un determinato modo, a volte nessuna di queste cose è importante. Per determinare come ricreare l'oggetto costante, COMPILE-FILE chiama la funzione generica MAKE-LOAD-FORM; questo comportamento dovrebbe essere descritto in qualsiasi riferimento CL o tutorial. (Un riferimento o tutorial dovrebbe anche notare che l'implementazione non può definire i metodi predefiniti MAKE-LOAD-FORM che sarebbero applicabili a tutte le istanze di STRUCTURE-CLASS o STANDARD-CLASS, e dovrebbe anche notare che MAKE-LOAD-FORM-SAVING -SLOTS è una comoda funzione da utilizzare nei metodi MAKE-LOAD-FORM per oggetti la cui inizializzazione non deve essere complicata, ad es.

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

Nota che quel metodo deve essere definito in fase di compilazione, in modo che COMPILE-FILE possa chiamarlo per determinare come salvare l'oggetto POINT costante.

Niente di tutto questo è specifico per CCL. Quale potrebbe essere la domanda su quali cose siano oggetti costanti, letterali e quali no.

In codice come:

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

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

al compilatore è consentito (ma non richiesto) di sostituire il valore di A-POINT con il riferimento ad esso nella funzione RETURN-A-POINT. (Se il compilatore lo fa, lo farebbe significa che c'è un oggetto POINT letterale / costante nel codice che viene compilato e COMPILE-FILE dovrebbe chiamare MAKE-LOAD-FORM per determinare come l'oggetto deve essere salvato e caricato; se il compilatore non esegue questa sostituzione, in questo esempio non è necessario chiamare MAKE-LOAD-FORM.)

Se un'implementazione fa questo tipo di sostituzione o meno dipende dall'implementazione. La specifica lascia inoltre non specificato se la forma del valore in una forma DEFCONSTANT viene valutata in fase di compilazione, in fase di caricamento o entrambe, e osserva che occorre prestare attenzione (dall'utente) per garantire che l'espressione valuti sempre lo stesso valore.

CCL generalmente cerca di valutare la forma del valore DEFCONSTANT in fase di compilazione ed è abbastanza aggressivo nel sostituire i valori delle costanti nominate con riferimenti ad esse; in alcuni casi, ciò significa che devono essere definiti i metodi MAKE-LOAD-FORM sulle classi dei valori delle costanti. Altre implementazioni potrebbero essere meno disposte a fare questa sostituzione per alcuni tipi di oggetti. Entrambe le strategie sono corrette e il codice portatile non può presumere quali strategie vengano seguite (anche se molto probabilmente il codice portatile fa tali assunzioni.)

Il diverso trattamento delle cose definito da DEFCONSTANT sembra la causa più probabile di questo tipo di cose (chiamate inattese a MAKE-LOAD-FORM che nessuno si è preso la briga di definire). Si possono evitare alcuni di questi problemi in un modo che dovrebbe essere portatile facendo:

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

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

Ciò avrà un effetto simile a quello di consentire semplicemente a un'implementazione che vuole farlo (come fa CCL) di effettuare una sostituzione costante, ma l'uso di LOAD-TIME-VALUE assicurerà che il valore costante sia valutato solo al carico tempo (e che MAKE-LOAD-FORM non sarà coinvolto.)

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