ラムダは究極のgoto
ラムダとgotoの区別がつかなくなってきた。
#include <stdio.h> int main(void) { int i = 10; int n; int acc; loop: if (i == 0) goto end; else { #define loop_dec_cont loop #define display_cont loop_dec #define fact_cont display n = i; acc = 1; goto fact; } loop_dec: i = i - 1; goto loop_dec_cont; display: printf("fact %d : %d\n", i, acc); goto display_cont; fact: if (n == 0) goto fact_cont; else { acc *= n; n = n - 1; goto fact; } end: return 0; }
うぅん。うまく書けない。
ジャンプしてるんじゃないんだ。gotoの先に展開される感じなんだよ。
TCCのソースを読むと、あたかもそこに関数があるかのように自然にgotoが使われてる。感動した。
ラムダは究極のgotoであると言えるかもしれない。
うまく書けない理由
そうだ。Cのgotoだけではうまく書けない理由がわかった。
「Cにはpusha,popaがない」
pusha,popaはアセンブリ命令で汎用レジスタの内容を全て保存する命令。pushaで前に作業してた環境を保存しておいて、popaで元の環境に戻す。残念ながらCには無い命令。
Cは、call > pusha > 関数の実行 > popa > ret。関数呼んだら、関数を呼んだところに戻る。
継続は、pusha > jmp > 関数の実行 > popa > jmpで、関数呼んでも、呼んだ先には戻らずそのまま継続していく。
呼んだ先には戻らず。というのがうまく書けないし、環境の保存も出来ない。
しかし、ジャンプしたり、環境を保存したりして、基本的な考え方自体はあんまり変わらないのかも。