Domanda

Io corro contro un problema nella comprensione del modo in cui CLOS di gestire l'accesso ai file all'interno di una classe. In C ++ sarei stato in grado di fare questo:

class Foo {
   Foo (string filename);  // opens the file (my_file) requested by the filename
   ~Foo ();  // close the file

   FILE * my_file;  // a persistent file-handle
   DataStruct my_data;  // some data

   void ParseData ();  // will perform some function on the file and populate my_data
   DataStruct * GetData () { return &my_data; }  // accessor to the data
};

Quello che mi piacerebbe sottolineare è che PraseData () sarà chiamato più volte, e ogni volta che un nuovo blocco di dati sarà analizzato dal file e my_data verrà alterata.

Sto cercando di eseguire lo stesso trucco in CLOS - creare tutti i metodi generici per analizzare i dati, caricare il file, leggere le intestazioni, ecc, nonché la definizione di classe, che ho come:

(defclass data-file ()
  ((filename :initarg :filename :accessor filename)
   (file :accessor file)
   (frame :accessor frame)))

Nel "costruttore" (vale a dire l'inizializzazione-esempio) ho aperto il file proprio come il mio c ++ linguaggio. Poi ho accesso ai dati e posso analizzare i dati come prima. Tuttavia, mi è stato detto che utilizzando un metodo (finalizzare) "distruttore", o di chiudere il file non è idiomatica CLOS per la gestione di questo tipo di situazione in cui ho bisogno del file di essere in giro in modo da poter accedere al di fuori dei miei dati file metodi.

ho intenzione di definire una funzione che carica un file di dati, e quindi esegue una serie di analisi con i suoi dati, e poi si spera chiuderlo. Che cosa è un modo per andare a fare questo? (Sto assumendo una macro o di un certo tipo di chiusura avrebbe funzionato qui, ma non sono abbastanza familiarità con il modo lisca di decidere ciò che è necessario o come implementarlo).

È stato utile?

Soluzione

Una possibilità è quella di avere il flusso come una fessura al posto del nome del file, e quindi la portata con CON-OPEN-FILE:

(with-open-file (stream file)
  (let ((foo (make-instance 'foo :stream stream)))
    (frob foo)
    (...other processing of foo...)))

Allora il vostro flusso verrà chiusa automaticamente.

Altri suggerimenti

Credo che avrei puntato a rendere le classi solo per memorizzare i dati autorevoli completi (quello che si chiama DataStruct?).

Non si ha realmente bisogno di una classe speciale per "carico + stoccaggio di un'altra classe". Inoltre, in questo modo ha l'invariante non detto che my_data contiene i dati di my_file fino alla posizione di cercare di corrente, che sembra un po 'strano per il mio occhio.

Detto in altro modo: che cosa fa Foo fare? Dato un nome di file, carica i dati, e ti dà un DataStruct. Che suona come una funzione per me. Se avete bisogno di essere in grado di eseguirlo in un thread, o di eventi di fuoco tra i record di carico, una classe è il modo naturale di farlo in C ++, ma non hai bisogno di una classe per quelle cose in Lisp.

Inoltre, ricorda che non è necessario utilizzare DEFCLASS al fine di utilizzare metodi generici in CLOS.

Non so quale sia la struttura dei vostri dati è, ma in situazioni simili ho fatto una funzione di analisi-un-pezzo che prende un flusso e restituisce un record, e quindi creare un'istanza completa Foo all'interno di un ciclo in un open-file con-. Se il flusso non è mai necessario al di fuori della portata di un'espansione open-file con-, non è necessario preoccuparsi di chiusura.

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