「Go言語でつくるインタプリタ」 (Thorsten (2018))を読みました。読みました、というか読んでインタープリタを実装し、一部の構文を追加で実装しました。書籍を購入したのが2022年5月、そこから一度チャレンジして諦め、2回目のチャレンジが2023年1月、3回目のチャレンジで読了できました。足掛け2年5ヶ月となかなか時間がかかり、途中しんどい時期もありましたが、読了できて良かったです。
ソースコードはこちらのリポジトリに置いておきました。GitHub Actionsで実装したインタープリタを実行して、FizzBuzzを動かすところまで書いてあります。
2022年5月にインタープリタを実装して学ぼうと思い立ち、最初に手に取ったのが本書「Go言語でつくるインタプリタ」でした(たぶん)。飽きたのか挫折したのか(おそらく後者)、最初のチャレンジは失敗に終わりました。
その後、「RubyでつくるRuby ゼロから学びなおすプログラミング言語入門」 (遠藤 (2017))という書籍に出会い、「Go言語でつくるインタプリタ」に再チャレンジする前に、こちらの本を先に読みました。
「RubyでつくるRuby」は、「Go言語でつくるインタプリタ」よりも入門的な書籍です。「Go言語でつくるインタプリタ」では構文解析のところから実装していきますが、「RubyでつくるRuby」では著者の実装したライブラリを利用することで構文解析の実装とその説明を省略し、読者は抽象構文木の評価のみを実装します。「RubyでつくるRuby」を読了すれば、Ruby(のサブセット)のインタープリタが完成します1。
「RubyでつくるRuby」を先に読んでおいて良かったと思ったことが一つあります。「Go言語でつくるインタプリタ」では構文解析の実装が終わらなければ動かすことのできない、実際にインタープリタを動かしてプログラムを実行する、というところを先にできたことです。実際、「Go言語でつくるインタプリタ」の後半の内容は、「RubyでつくるRuby」で学習済みの内容が多く、既視感を感じながら実装することになりました。
ゴールが見えていることで、「先の見えなさ」からくるモチベーションの低下がなくなりました。
内容を十分に理解できなかったこともありますが、同じような実装が続いて飽きてしまうためです。今回の3回目のチャレンジでも、飽きとの戦いがありました。しかし、前よりもインタープリタの理論を理解できてきたこと、Go言語についても理解を深めたことで、何とか読了することができました。
FizzBuzzを実装するために剰余演算子が欲しかったので、インタープリタを拡張して剰余演算子を実装しました。20分くらいで実装できて感動しました。
最終的に、こんな感じでFizzBuzzを実装しました。
let fb = fn(n) {
if (n > 1) {
fb(n - 1);
};
if (n % 15 == 0) {
puts("FizzBuzz");
return;
}
if (n % 3 == 0) {
puts("Fuzz");
return;
}
if (n % 5 == 0) {
puts("Buzz");
return;
}
puts(n);
};
fb(100);
読んでいる途中は「楽しい」という感覚はあまりありませんでしたが、いざ完成して自分で書いたプログラムを動かせるようになるととても楽しいです!また、言語処理型の気持ちがすこしだけわかるようになった気がします🤏
関数の評価のところが、どうしても正しく実装できませんでした。全体を何度も見直して、エラッタも読みましたが…。もう1回、「RubyでつくるRuby」にもチャレンジしてみようかなと思っています。 ↩︎