类中的lisp文件指针

时间:2009-11-04 17:17:47

标签: lisp class-design common-lisp clos

我遇到了解CLOS处理类中文件访问方式的问题。在c ++中,我可以这样做:

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

我想指出的是PraseData()将被多次调用,每次从文件中解析出一个新的数据块,my_data就会被更改。

我正在尝试在CLOS中执行相同的技巧 - 创建所有通用方法来解析数据,加载文件,读取标题等,以及我所拥有的类定义:

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

在“构造函数”(即initialize-instance)中,我打开文件就像我的c ++习语一样。然后我可以访问数据,我可以像以前一样解析数据。但是,我被告知使用“析构函数”或(finalize)方法来关闭文件不是惯用的CLOS来处理这种情况,我需要文件在那里,所以我可以在我的数据文件之外访问它方法

我将定义一个加载数据文件的函数,然后对其数据执行一系列分析,然后希望将其关闭。这是怎么回事? (我假设一个宏或某种类型的闭包可以在这里工作,但我不熟悉lisp方式来决定需要什么或如何实现它。)

2 个答案:

答案 0 :(得分:6)

一个选项是将流作为插槽而不是文件名,然后使用WITH-OPEN-FILE将其作为范围:

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

然后您的信息流将自动关闭。

答案 1 :(得分:3)

我想我会倾向于只创建类来存储完整的权威数据(你称之为DataStruct?)。

你真的不需要一个特殊的类来“加载+存储另一个类”。另外,这种方式具有未说出的不变量,即my_data将my_file的数据保存到当前的搜索位置,这对我来说似乎有点奇怪。

换句话说:Foo做什么?给定文件名,它会加载数据,并为您提供DataStruct。这对我来说听起来像是一种功能。如果你需要能够在一个线程中运行它,或者在加载记录之间触发事件,那么类是在C ++中执行它的自然方式,但是你不需要在Lisp中为这些东西创建一个类。

另外,请记住,您不需要使用DEFCLASS来在CLOS中使用泛型方法。

我不知道你的数据的结构是什么,但在类似的情况下,我做了一个parse-one-chunk函数,它接受一个流并返回一条记录,然后在一个循环中创建一个完整的Foo实例在一个打开文件中。如果在with-open-file扩展的范围之外永远不需要流,您永远不必担心关闭它。