ぱろっと・すたじお

技術メモなどをまったりと / my site : http://parrot-studio.com/

Scalaで末尾再帰的なBrainF**kインタプリタを書いてみた

少し時間が空いたので、以前読んだ本に従って、
ScalaLispインタプリタを実装しようとか考えていたのですが、
非常に考えが甘かったのですΣ(゚Д゚)ガーン

つくって学ぶプログラミング言語 RubyによるScheme処理系の実装 - 達人出版会

Scalaに全然なじんでないのもありますが、
RubyLisp的な思想で設計されているから簡単そうに見えるのであって、
静的型付けのScalaだといろいろ面倒だったんですよね・・・

そこで引き下がるのも負けた気がするので、
何か実装しようと考えていたところ、
BrainF**k(以下BF)でいいじゃないかと思い当たりまして

そもそも私は以前、汎用的なBFインタプリタ製造器を作ってます

なので、BFの構造については熟知しており、
これなら簡単なんじゃないかな・・・と

ただし、Scalaで書く以上、「全て副作用のないコード」という制限をつけました
でないと、ただRubyのロジックをScalaで実装し直すだけになりますし

まあ、実際に書いてみるといろいろ行き詰まると思っていたのですが、
結果的にあっさり書けました
しかも、Ruby版よりはるかにわかりやすくΣ(゚Д゚)ガーン *1

BrainF**k interpreter by Scala

100行程度のコードですが、肝は実行系である「Machine」クラスです
ご覧の通り、各命令に対して何をしているか、
見ただけでわかるコードになりました(`・ω・´) b

しかも、静的型付けのおかげで、
インターフェースさえ確定してしまえば、
コンパイラが問題を指摘してくれるのはやはり楽です*2

こんな感じで、思ったよりあっさり書けて喜んでいたのですが、
再帰的な構造にした分、スタックを食いつぶしている可能性に思い当たりまして

resultを引き回している=結果の値を待ってないし、
自身に「丸投げ」しているから大丈夫とは思いつつ、
一応アノテーションをつけてみたところ、エラーにはなりませんでした *3

たぶん大丈夫とは思いますが、おかしければぜひ指摘を(`・ω・´)ノ

*1: もちろん、Ruby版は汎用的にインタプリタを生成する仕組みであり、Parser部分が複雑だったり、実行系にオプションをつけたりできるのですが、Machine部分でやろうとしている範囲はほとんど同じです

*2: Rubyのような動的型付けが悪いのではなく、副作用の混入しづらいロジカルなコードにおいては、静的型付けが使いやすいってことで、やはり適材適所です

*3: executeの下請けとしてstepExecuteが存在し、stepExecuteは値を全部引き回している・・・という構造を考えると、たぶん大丈夫なのですが