类中的 lisp 文件指针
我在理解类中处理文件访问的 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)))
在“构造函数”中(即初始化-instance) 我就像我的 C++ 习惯用法一样打开文件。然后我就可以访问数据并且可以像以前一样解析数据。然而,我被告知使用“析构函数”或(最终确定)方法来关闭文件并不是惯用的 CLOS 来处理这种类型的情况,我需要文件在周围,以便我可以在数据文件之外访问它方法。
我将定义一个函数来加载数据文件,然后对其数据执行一系列分析,然后希望将其关闭。有什么方法可以做到这一点? (我假设宏或某种类型的闭包可以在这里工作,但我不太熟悉 lisp 方法来决定需要什么或如何实现它)。
I'm running up against a problem in understanding the CLOS way of handling file access within a class. In c++ I would be able to do this:
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
};
What I'd like to point out is that PraseData() will be called multiple times, and each time a new block of data will be parsed from the file and my_data will be altered.
I'm trying to perform the same trick in CLOS - create all the generic methods to parse the data, load the file, read headers, etc. as well as the class definition which I have as:
(defclass data-file ()
((filename :initarg :filename :accessor filename)
(file :accessor file)
(frame :accessor frame)))
In the "constructor" (i.e. initialize-instance) I open the file just as my c++ idiom. Then I have access to the data and I can parse the data as before. However, I'm told that using a "destructor" or (finalize) method to close the file is not idiomatic CLOS for handling this type of situation where I need the file to be around so I can access it outside of my data-file methods.
I'm going to define a function that loads a data-file, and then performs a series of analyses with its data, and then hopefully close it. What's a way to go about doing this? (I'm assuming a macro or some type of closure would work in here, but I'm not familiar enough with the lisp way to decide what is needed or how to implement it).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一种选择是将流作为槽而不是文件名,然后使用WITH-OPEN-FILE对其范围进行限制:
然后您的流将自动关闭。
One option is to have the stream as a slot instead of the filename, and then scope it with WITH-OPEN-FILE:
Then your stream will be closed automatically.
我想我会倾向于只创建类来存储完整的权威数据(你称之为 DataStruct?)。
您实际上并不需要一个特殊的类来“加载+存储另一个类”。另外,这种方式有一个不言而喻的不变量,即 my_data 将 my_file 的数据保存到当前的查找位置,这在我看来有点奇怪。
换句话说:Foo 是做什么的?给定一个文件名,它会加载数据,并为您提供一个 DataStruct。这对我来说听起来像是一个函数。如果您需要能够在线程中运行它,或者在加载记录之间触发事件,那么在 C++ 中使用类是实现此目的的自然方法,但在 Lisp 中不需要为这些事情使用类。
另外,请记住,您不需要使用 DEFCLASS 即可在 CLOS 中使用通用方法。
我不知道你的数据的结构是什么,但在类似的情况下,我制作了一个解析一块函数,它接受一个流并返回一条记录,然后在 with 的循环内创建一个完整的 Foo 实例-打开文件。如果在 with-open-file 扩展的范围之外永远不需要该流,则您永远不需要担心关闭它。
I think I would lean towards making classes only to store complete authoritative data (what you call DataStruct?).
You don't really need a special class for "loading + storage of another class". Plus, that way has the unspoken invariant that my_data holds the data of my_file up to the current seek position, which seems a bit strange to my eye.
Put another way: what does Foo do? Given a filename, it loads data, and gives you a DataStruct. That sounds like a function to me. If you need to be able to run it in a thread, or fire events between loading records, a class is the natural way to do it in C++, but you don't need a class for those things in Lisp.
Also, remember that you don't need to use DEFCLASS in order to use generic methods in CLOS.
I don't know what the structure of your data is, but in similar situations I've made a parse-one-chunk function that takes a stream and returns one record, and then create a complete Foo instance inside a loop in a with-open-file. If the stream is never needed outside the scope of a with-open-file expansion, you never need to worry about closing it.