Vol.1の『「コルーチン」とは何だったのか』を読んでいる。勉強がてら、Rでコルーチンを実装してみることにした。今回は元祖コルーチンとして紹介されている対称コルーチンを扱う。対称コルーチンでは、関数AとBが互いを関数中で呼び合い、未実行な部分から次に相手を呼び出すところまでを順次実行していくものらしい。Vol.1には疑似コードも含めて紹介されているので、詳しくはそちらを参照して欲しい。疑似コードがわざと抱えているバグを修正コルーチンを簡単に書けるようにするメタプログラミングの3本仕立てでお送りする。Rでコルーチンが活躍する場面はほとんどないだろう。Vol.1にて紹介されている疑似コードをRで実装してみよう。関数AとBのどこまでを実行したか管理するために、環境をiに割り当てた。時は、これらの値を1に書き換えた上で前半の処理を実行する。NULL以外の時は後半の処理を実行する。"A-end"ラムダノート上でも指摘されている通り、中断したコルーチンを再開し忘れているので、"B-end"が出力されない。ルーチン終了時に実行状況を初期化していないため、もう一度コルーチンを走らせると、"A-end"のみが出力されてしまう。上述のバグを修正するとやや複雑なコードが生まれる。"B-end"見事、"B-end"まで出力された。"B-end"一般化コルーチン内の処理の数が増えるごとに、if文を書き連ねていくのは地獄だ。そこで、コルーチンを生成する関数coroutineを書いてみよう。呼び出しごとに実行したい処理の内容とする。処理内容は任意の個数書けるように、省略記号...を用いる。rlang::enquos関数を用いると、省略記号に指定した処理を表現式として保存しておくことができる。後は今が何度目のルーチン呼び出しかを管理し、i番目であれば、省略記号に指定したi番目の処理をrlang::eval_tidyによって実行すれば良い。}}coroutine関数を使ってラムダノートの例にあったコルーチンを実装してみよう。"B_end"iは適切に初期化されているので、二度目以降の呼出にも対応する。"B_end"ShareHome。