代码之家  ›  专栏  ›  技术社区  ›  Shamster

类中的lisp文件指针

  •  2
  • Shamster  · 技术社区  · 17 年前

    在理解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
    };
    

    我要指出的是,prasenta()将被多次调用,每次从文件中解析一个新的数据块时,我的_数据都将被更改。

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

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

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

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

    2 回复  |  直到 17 年前
        1
  •  6
  •   Xach    17 年前

    一个选项是将流作为槽而不是文件名,然后使用-open-file对其进行作用域:

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

    然后您的流将自动关闭。

        2
  •  3
  •   Ken    17 年前

    我认为我倾向于使类只存储完整的权威数据(您称之为数据结构?).

    你不需要一个特殊的类来“加载+存储另一个类”。另外,这种方式还有一个无法言喻的不变量,即我的_数据将我的_文件的数据保存到当前的查找位置,这在我看来有点奇怪。

    换一种方式:foo做什么?给定一个文件名,它将加载数据,并为您提供一个数据结构。这听起来像是一个功能。如果需要能够在线程中运行它,或者在加载记录之间触发事件,则类是在C++中自然完成的一种方法,但是对于Lisp中的那些类,您不需要一个类。

    另外,请记住,在CLO中使用泛型方法不需要使用defclass。

    我不知道您的数据的结构是什么,但是在类似的情况下,我创建了一个parse-one-chunk函数,它获取一个流并返回一个记录,然后在with-open文件的循环中创建一个完整的foo实例。如果不需要在具有打开文件扩展的范围之外使用流,则无需担心关闭它。

    推荐文章