関数型言語を実装すれば分かるやろ入門①

関数型言語を実装すれば分かるやろ入門①

どうも、Lisp方言Scheme言語好き自称ハッカーののどかはです。


関数型なんて結局分からんやろということで、実装していきましょう。


今回は簡単に説明を目指していきますが、分からなければ積極的に聞いてもらえればと思います。
まあ、あとこれを理解することがなにに繋がるかは分からないので、話半分理解出来ればとても面白いと思います…多分

PCについて


PCっていうものは便利ですね。


PCってどんな風に出来てるでしょう。
はい、分からないですね。
なので想像してみることにします。


PCは箱に入ってるので、きっと箱の中に沢山夢が詰まっている楽しい機械だと思います。


夢が入ってるということは、きっと夢の元となる沢山の夢の欠片から出来ていそうなので、それはなんなのか考えてみましょう。

レジスタと計算という存在


夢を考えますが、夢は多分コンピューターにとってのなので、それがどう頑張っても数字で出来てそうだなあという絶望に気付きます。


私達は人であるので、ちょっとコンピュータくんたちの夢を正確に理解することは出来なさそうです。


でも私達は賢い人間ですので、算数が出来ます。
計算さえ出来ればコンピュータの夢を誰かに説明することは出来そうなので、ちょっと頑張ってみましょう。


ここで、夢を作るための欠片、PCの扱える箱達をレジスタと呼ぶことにします。


なんでなんて言われても偉い人が決めたので、ちょっと認めてあげてください。


偉い人達も最初は偉くないけど、こういう意味分からない名前を沢山つけたことで偉くなったので。

書いてみる


これからC言語を書いていきますが、実際に試すような感じでは書かず、理解のための疑似コードだと思ってもらって構いません。


また、分からなくなったら、C言語の入門とにらめっこしながら見てみてください。


無理はしなくても、なんかこんな処理かなあで大丈夫です。


さて愚直にレジスタなので、レジスタっていう変数くんを用意します。

int r;int registers(){return r;}


こういう簡単なコードばかり見ると退屈になっちゃうかも知れませんが、しばらくは我慢してください。


いきなりコードが増えていくと何故か理解出来なくなる、エンジニアの理解は指数法則的にワカランになる法則があるので、我慢していきましょう。


次に夢を詰めれないと困るので夢を詰めれるようにしましょう。


私達はコンピュータくんの夢の内容が分からないので今はnullを詰めてあげます。
は~いコンピュータくーん、新鮮な無だよ~。

int returnNull(){return NULL;}

次にその箱を初期化(空に)できるようにします

int initRegisters(){r = 0;return r;}

これでmain関数で色々出来る用意が出来ました

int main(void){initRegisters();printf("register r = %d\n", registers());printf("新鮮な無 %d\n", returnNull());return 0;}


もちろんおまじない(stdio.hのインクルード)は忘れずに行なっておいてくださいね


全体を書き終わってコンパイルすれば出力されます

register r = 0新鮮な無 0


おめでとうございます

役割という話


int r;という変数をグローバルに宣言して初期化したり値を取り出したりしました


これは一体なんでしょう?


レジスターっていうのはPCにとっての数を扱う箱だと言いました


という事はPCくんにとってはこれがデータを扱う手段です


さて、我々は関数型言語を作りたい訳なので、扱うのはデータだけでなく関数を扱わなければなりません


ということで同じように考えます(どうして同じように考えて良いかは今は言及しません)


まったく同じものをコピペして型だけを変えます

void (*e)(void);
void* initEnvironments()
{
e = NULL;
return e;
}
void* environments(){return e;}

おまけ


テストが大事だなあと思ったので、テストを書いたんですがこんな複雑なものあってもしょうがないし、説明が面倒なのでここで供養します

int testAll(){int pass=0;int error=0;void (*testFunc[])(void) = {&registers, &returnNull};void *testDataList[][2] = {{10, 10, 1}, {NULL, NULL, 0}, NULL};int testFuncLength = 2;for(int n=0;n<testFuncLength;n++){if (1 == test(testFunc[n], testDataList[n][0], testDataList[n][1], testDataList[n][2])){pass++;printf("pass\n");} else {error++;printf("error\n");}}printf("test pass : %d, error : %d\n", pass, error);return 0;}
int test(void (func)(void), void* checkValue, void* registerValue, void* type_p){printf("checkValue = %d\n", (int)checkValue); printf("registerValue = %d\n", (int)registerValue);printf("return %d\n", func());int type = (int)type_p; printf("type = %d\n", type); if(0 == type){ return NULL == func(); }else if(1 == type){ r = registerValue; int v = (int)checkValue;int a = func();printf("test %d == %d\n", v, a);return v == a;}}


読まなくて大丈夫です

この記事の著者Writer

のどかは

望み通り叶えるのは「のどかは」BlossomsArchiveに間借りして、CTFを語る謎のぶいあーるちゃったーかもしれない大した記事は投稿しません

TOP