Pergunta

Eu estou correndo contra um problema na compreensão da maneira CLOS de lidar com acesso a arquivos dentro de uma classe. Em C ++, eu seria capaz de fazer isso:

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
};

O que eu gostaria de salientar é que PraseData () será chamado várias vezes, e cada vez que um novo bloco de dados será analisado a partir do arquivo e my_data será alterado.

Eu estou tentando executar o mesmo truque em CLOS - criar todos os métodos genéricos para analisar os dados, carregar o arquivo, ler cabeçalhos, etc., bem como a definição de classe que tenho como:

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

No "construtor" (ou seja, initialize-exemplo) eu abrir o arquivo tal como o meu c ++ idioma. Então eu tenho acesso aos dados e posso analisar os dados como antes. No entanto, me disseram que o uso de um método (Finalizar) "destruidor" ou para fechar o arquivo não é CLOS idiomáticas para lidar com este tipo de situação onde eu preciso o arquivo a ser em torno para que eu possa acessá-lo fora do meu arquivo de dados métodos.

Eu estou indo para definir uma função que carrega um arquivo de dados, e em seguida, executa uma série de análises com os seus dados, e então espero que fechá-lo. O que é uma maneira de ir sobre como fazer isso? (Estou assumindo uma macro ou algum tipo de fechamento iria trabalhar aqui, mas eu não sou suficientemente familiarizado com a maneira lisp para decidir o que é necessário ou como implementá-lo).

Foi útil?

Solução

Uma opção é ter o fluxo como um slot em vez do nome do arquivo, e alcance então com COM-OPEN-FILE:

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

Em seguida, o fluxo será fechada automaticamente.

Outras dicas

Eu acho que eu inclinar-se para fazer aulas apenas para armazenar dados oficiais completos (o que você chama DataStruct?).

Você não realmente precisa de uma classe especial de "carregamento + armazenamento de outra classe". Além disso, dessa maneira tem a invariante tácita de que my_data contém os dados de my_file-se à a posição atual, que parece um pouco estranho para meus olhos.

Dito de outra forma: o que Foo fazer? Dado um nome de arquivo, ele carrega os dados, e dá-lhe um DataStruct. Isso soa como uma função para mim. Se você precisa ser capaz de executá-lo em um segmento, ou eventos de fogo entre os registros de carga, uma classe é o caminho natural para fazê-lo em C ++, mas você não precisa de uma classe para essas coisas em Lisp.

Além disso, lembre-se que você não precisa usar DEFCLASS a fim de utilizar métodos genéricos em CLOS.

Eu não sei o que a estrutura de seus dados são, mas em situações semelhantes Eu fiz uma função de análise-um-pedaço que leva um fluxo e retorna um registro, e em seguida, criar uma instância de Foo completa dentro de um loop em um arquivo aberto com-. Se o fluxo nunca é necessário fora do âmbito de uma expansão de arquivos abertos com-, você nunca precisa se preocupar em fechá-lo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top