System Lufimia 作業状況報告書 へ

read-eval-printループ

 今日のこの時点ではファイルの読み書きができたという程度なんですが、この検証作業をしているwindows上のcygwin環境におけるCのソース ファイルって実は若干違っています。その冒頭部分を公開しちゃいますと……

#include <stdio.h>

#define MAX_INBUFFER 4096

char inbuffer[MAX_INBUFFER];
int i;

FILE *fpin,*fpout;

main(){
    read();
    eval();
    print();
}
(以下略)

main関数を見てほしいのですが、C言語の入門書でこんな関数を最初に書いちゃう本ってまずないと思います。
 これは、LISP言語の影響だと思います。LISPって言語の解説書の多くが「LISPでLISP自身を書いてみよう。自分で処理系作ってみよう。」と いう課題を扱うんですね。じゃあなんでLISPでLISP自身を書けるのかというと、それは「read関数で読み込み、eval関数で評価して、その結果 をprint関数で返すんだ。その繰り返し。」と説明するのです。
 この点が、私がlispを好きな理由の1つなのです。
 そして他の言語でプログラミングする時も、read-eval-printループを意識して書くようにしているのです。Cなど手続型言語だと、メインな り冒頭でread-eval-printループを書くとか、表計算ソフトを使う時も入力シートと途中の処理用のシートと出力シートとを分けて使うと か……。

特にフィルターについて

 UNIXの世界だとフィルターというプログラム……というか考え方を多用しますね。標準入力と標準出力という概念があって、入出力は特に指定しない限 り、標準入力と標準出力が指定される。また標準入力や標準出力を切り替えることにより、それ以外の入出力も扱える。そのことから、複数のフィルタを(パイ プで)つないで複数の仕事をさせることができる……と。
 これも私の手にかかればread-eval-printループの延長ってことになってしまいます。ループじゃなくて1回限りだってことですし、実は1回 限りかループかというのは本質的な差ではありません。出力を入力に使えるかどうかがポイントですし、lispでは出力を入力に使うことがこれまた簡単で す。
 というので、私がプログラミングする時はread-eval-printループで考えるのでした。
 ……個人的にはこの発想はオブジェクト指向とも衝突はしないと思っているんだけど……。どうもJAVAがいまいちピンと来ないのは実は衝突するせい?

参考までにフィルターの一例。

#include <stdio.h>

int ch1,ch2;


main(){
    ch1 = getchar();
    while ( ch1 != EOF ) {
        process();
        putchar( ch2 );
        ch1 = getchar();      
    }
}

process(){
    ch2 = ch1;
}

標準入力から1byte読んで(getchar、putcharは標準入出力固定)
process関数に渡し、結果を標準出力に出力するというもの。
実際にはprocessの中ではコピーしているだけですが
そこでいろいろやるといろいろできるという仕掛け。
入力だってここでは1byte読むだけですが
1行読むとか一定byte一気に読むとか
いろいろ改造できます。
改造のネタとしてご紹介。

System Lufimia 作業状況報告書 へ