【问题标题】:lisp file pointers in classes类中的 lisp 文件指针
【发布时间】:2010-12-13 02:49:10
【问题描述】:

我在理解类中处理文件访问的 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)))

在“构造函数”(即初始化实例)中,我打开文件就像我的 c++ 习惯用法一样。然后我可以访问数据,并且可以像以前一样解析数据。但是,有人告诉我,使用“析构函数”或(finalize)方法来关闭文件不是惯用的 CLOS 来处理这种我需要文件存在的情况,以便我可以在我的数据文件之外访问它方法。

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

【问题讨论】:

    标签: lisp class-design common-lisp clos


    【解决方案1】:

    一种选择是将流作为一个槽而不是文件名,然后使用 WITH-OPEN-FILE:

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

    然后你的信息流会自动关闭。

    【讨论】:

    • 早起的鸟儿有答案
    【解决方案2】:

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

    你真的不需要一个特殊的类来“加载+存储另一个类”。另外,这种方式有一个不言而喻的不变量,即 my_data 将 my_file 的数据保持到当前的搜索位置,这在我看来有点奇怪。

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

    另外,请记住,您无需使用 DEFCLASS 即可在 CLOS 中使用泛型方法。

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

    【讨论】:

    • 我无法解析其中的一些内容,但感谢您的见解。没错,Foo 加载一个文件并返回一个 DataStruct,但它也保存文件指针。如果文件已关闭读取某些数据,我将需要寻找新位置 - 使用每个新数据帧更新文件指针。我从您的评论中收集到的是,与其使用单个对象来操作文件流并解析数据,不如创建一个可以采用给定文件流进行数据解析的对象并管理文件并在其他地方流式传输。准确吗?
    • 我想我对你的评论同样感到困惑。 “创建一个可以采用给定文件流进行数据解析的对象”->当然,这个“对象”我称之为“函数”。 :-) 我在这里并没有真正看到“class Foo”背后的目的。没有继承发生。它有一个输入、一个输出、一个临时和一些在开始、中间和结束时运行的代码。在我的世界里,它描述的是一个函数,而不是一个类。但我并不完全理解上下文。
    • 肯:说得好。在学习形成函数/类时,我一直被困在一个特定的习惯中,所以我很欣赏这种洞察力。在这种情况下,除了 DataStruct 之外,没有理由创建一个对象来保存“权威数据”并编写函数来围绕它执行流操作。
    猜你喜欢
    • 1970-01-01
    • 2016-06-20
    • 2013-02-20
    • 1970-01-01
    • 2016-03-04
    • 2021-11-06
    • 2014-09-17
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多