2

クラス内でファイル アクセスを処理する 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++ イディオムと同じようにファイルを開きます。その後、データにアクセスできるようになり、以前と同じようにデータを解析できます。ただし、「デストラクタ」または(ファイナライズ)メソッドを使用してファイルを閉じることは、データファイルの外部にアクセスできるようにファイルが必要なこの種の状況を処理するための慣用的なCLOSではないと言われていますメソッド。

データ ファイルをロードし、そのデータを使用して一連の分析を実行し、できればファイルを閉じる関数を定義します。これを行う方法は何ですか?(私は、マクロまたは何らかのタイプのクロージャがここで機能すると想定していますが、何が必要か、またはそれをどのように実装するかを決定する Lisp の方法に十分に精通していません)。

4

2 に答える 2

6

1 つのオプションは、ストリームをファイル名ではなくスロットとして使用し、WITH-OPEN-FILE でスコープを設定することです。

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

その後、ストリームは自動的に閉じられます。

于 2009-11-04T18:48:23.187 に答える
3

私は、完全な信頼できるデータ(DataStructと呼ばれるもの)を格納するためだけにクラスを作成することに傾倒すると思います。

「別のクラスのロード+ストレージ」のための特別なクラスは実際には必要ありません。さらに、その方法では、my_dataがmy_fileのデータを現在のシーク位置まで保持するという暗黙の不変条件があります。これは私の目には少し奇妙に思えます。

別の言い方をすれば、Fooは何をするのでしょうか?ファイル名を指定すると、データが読み込まれ、DataStructが提供されます。それは私には機能のように聞こえます。スレッドで実行したり、レコードの読み込みの間にイベントを発生させたりする必要がある場合は、C ++でクラスを実行するのが自然な方法ですが、Lispではそれらのクラスは必要ありません。

また、CLOSでジェネリックメソッドを使用するためにDEFCLASSを使用する必要がないことを忘れないでください。

データの構造はわかりませんが、同様の状況で、ストリームを取得して1つのレコードを返す、チャンクを解析する関数を作成し、ループ内に完全なFooインスタンスを作成しました。 -ファイルを開きます。with-open-file拡張の範囲外でストリームが必要にならない場合は、ストリームを閉じることを心配する必要はありません。

于 2009-11-04T19:57:45.030 に答える