ぱろっと・すたじお

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

KotlinでいつものBrainF**kインタプリタを書いてみた件(+学んだ本が良かった件)

以前から話には聞いていたものの、
最近「ことりんはいいぞ・・・!」という話を聞く機会があったので、
試しに本を読んでみたわけです

Kotlinプログラミング

Kotlinプログラミング

この本がKotlin抜きに非常に良い本でして、
Kotlin自体もいい感じだとわかったので、
例によってBrainF**kインタプリタを書いてみました(´・ω・)っ

gist.github.com

これで「現場からは以上です」って感じなのですが、
以下は自分用のメモであり蛇足です...φ(・ω・`)


「今風の言語」とは何か?

1. 「人間」にとって都合の良い言語

仕様を読んでみて、Kotlinは非常に「今風の言語」だと思ったのですが、
何をもって「今風」なのか・・・と考えてみたわけです

そもそも、一番CPUに近い言語は「アセンブラ」であり、
それをもうちょっと人が書きやすくしたのが「C」、
そこにオブジェクト指向パラダイムを付加したのが「C++」や「Java」でした

「プログラムとは、本質的にメモリを操作する仕組みに過ぎない」というのは、
こちらの本にも書かれている本質的な話でして・・・

・・・Javaも極論を言えば
mallocとポインタを言いかえただけ」と見なすことが可能ですΣ(・ω・ノ)ノ

そういったCPUというかアセンブラから派生した言語とはまた別に、
「人にとって都合の良いモデル・処理系」を提唱したのが「Lisp」でして、
その影響を受けたJavaScript*1Rubyは非常に柔軟です

しかし、「人にとって都合がいい」は「CPUにとっては重い」ってことなので、
Rubyも長いこと「遅くて使えない」と言われていたのが、
CPUの高速化によって価値が再認識されたわけです*2

「わかりやすく言いかえる」というのが「人間」にとっては重要で、
オブジェクト指向」も本来的には「現実世界をモデル化する概念」ですし、
「関数型」も「数学の概念のモデル化」にすぎません

まあ、当時の関数型言語ブームは少々アカデミックに走りすぎて、
「なんかよくわからないけど難しい」になってしまっていたのはありますが(´-ω-)

今ではオブジェクト指向とか関数型の概念は、
もはやそのような単語が言語の文脈に出てこない程度には、
「当たり前のもの」として扱われるようになっております

2. 「型」の取り扱いと「設計思想」

さて、RubyJavaも「オブジェクト指向パラダイムを含んだ言語」ですが、
決定的に違うのが「型」の扱い方です

Javaは変数に型を要求するのが当たり前*3であり、
Rubyは「そのメソッドが呼べればOK」というゆるい縛りしかありません
(いわゆる「ダックタイピング」)

Rubyはその表現力ゆえに「Rails」という「実装された設計思想」を生み出し、
現在のWebフレームワークはほぼRailsに影響を受けているわけです

一方で、Webが肥大化するにつれ、
モノリシックなフレームワークで抱えられる規模を超えると、
「自由度が高いこと」は必ずしも利点ではなくなってきます

もちろん、先日書いたようにアーキテクチャ設計でカバーできる場合もありますが・・・

parrot.hatenadiary.jp

・・・ここまでコストを割けるのはかなり限られたケースでしょう

そもそも、どんな「できるエンジニア」であっても、
「人が認識できる規模」にはどうしても限界があり、
それを超えれば確実にミスを生みます

だからこそ、「設計上の制約」を「コードレベルで表現する」のが必要で、
その手段の一つが「型」と言えます

「じゃあJavaにすればいい」というのはよくわかるし、
実際に業務系システムではまだ圧倒的なシェアがあるのですが、
どうしても他の言語に比べて「お堅いので書きづらい」のはあります(´-ω-)

結局は「いちいち型を書く」のが面倒なのであり、もっといえば
「人が見ればわかることをいちいち書かないといけないのが冗長」ということでしょう

String hello = "Hello World!";

要は、「helloに文字列を代入してるんだから、
helloがStringなのわかるやん? わからんの(´・ω・)?」ということで、
いわゆる「型推論」ができないのか・・・ってことです

「人間にわかること」と「CPUにわかること」には乖離がありますが、
CPUの進化により、「現実的な時間」で推論が可能になったため、
最近の言語はだいたい型推論を備えています

最近のJavaにも一応備わっているらしいですが、
「関数型っぽい型=高階関数」までは扱えない・・・か、
扱いづらいか、対応がまだ不十分かのようです(´・ω・`)

(Java8で改善されたことは知っているものの、触れる機会がなかったので、
 このあたりの私の理解はあいまいです)

そこで、「JVMで動く関数型言語」として「Scala」が出てきたし、
私も一時期は興味があったわけですが・・・

やはり、先ほども書いたように、HaskellScalaのような言語は、
「純粋な関数型言語」を「アカデミックな思想」で目指しており、
「普通の人には難しい(と見える)」のが問題なのではないかと

Rubyが広まったのはその柔軟性もありますが、
やはり「プログラムを楽しく書きたい」という「思想」の面が強いわけです
良くも悪くも、「現実的な妥協」が入っている

Kotlinは「純粋な関数型言語」ではありませんが、
高階関数」や「再代入不可」のような、
Rubyと同程度以上の関数型言語的なパラダイムを備えています

その上でKotlinの「思想」は「よりベターなJava」であり、
非常に「Javaとの連携」を強く意識しています

Javaのclassとの暗黙的相互運用な可能な点は、
まさに「現場が望んだのだからそうあるべき」という思想を感じます(`・ω・´) b

結局のところ、「今風の言語」の個人的な定義はこうなるのかなと

  • 「思想」が感じられ、「現実的なバランス」に落とし込んでいる
  • 関数型のパラダイムを「現実的に便利な部分だけ」引き継いでいる
  • 過去に存在した言語との相互運用性を意識している

その意味で、JavaScriptに対する「TypeScript」と、
Javaに対する「Kotlin」は同じなんだろうな・・・と*4

考えてみると、TypeScriptもKotlinも(ついでに C# *5 も)「企業」が開発した言語です
それだけ、「現場の声」が反映されていたり、
「現場で使われるIDEとの連携」を意識している・・・ということですね

3. Rubyエンジニアから見たKotlin

Rubyのエンジニアからすると、
Kotlinは「Rubyっぽくて書きやすいJava」ですが、
明確な違いがあります

それは「変更に対してオープンかクローズか」という違いです

Rubyにおいて、あらゆるものは上書き可能であり、
それゆえに「黒魔術」とも呼ばれる柔軟なメタプログラミングが可能です
これを利用してgemにモンキーパッチをあてる・・・というのもよくあります

言いかえると、「誰かが勝手にまずいことをやってしまうことを防げない」ので、
ある人が良かれと思って変えたクラスの変更が、
他に波及して壊れる・・・ということもあります(´-ω-)

モンキーパッチにしても、当時はわかっていてやったとしても、
あとになると忘れてしまい、gemが更新できず、
右往左往する・・・ってことがよくあります
(ゆえに、私はgemやフレームワーク自体にパッチをあてるのは否定的です)

それはプログラマの質とかチームの問題である・・・という「思想」なのですが、
大規模なシステムでそういった「やってほしくないこと」を防ぐのは、
「現実的に考えると」難しいです

その点、Kotlinは「クローズ」がデフォルトで、
「必要な時に明示する」という「思想」です

クラスだけでなく、メソッド単位で宣言が必要なのは「面倒」ですが、
「面倒だから面倒ではない手段を探す」ように誘導しているのはあります
(これはRubyの設計思想も同じ)

また、「良くないことをしている場所」をあとから探すのが容易になるのも利点です
Javaでもアノテーションとかありますが、
「言語仕様で強制」はできませんからね(´-ω-)

だからRubyよりKotlinが優れている・・・ということではなく、
あくまで「適用範囲を良く考えよう」ということです

一般的なWebの文脈においてはRubyが楽だけど、
業務系システムですでにJVMの実績があればKotlinだよね・・・みたいな...φ(・ω・`)

冒頭の本は何がいいのか?

先ほどもちょっと挙げたこちらの本を、私は以前から絶賛しております

parrot.hatenadiary.jp

www.slideshare.net

この本のすばらしい点は、「とにかく実装を進めていって、
必要になったらあたらしい概念を導入する」というのを徹底している点です
なにしろ、「変数」が出てくるのが後半ってレベルです

同様に、先ほどのKotlinの本も、
「Kotlinの機能を必要になったら紹介する(という体で書かれている)」のが重要で、
「この機能はどういう時に使うと適切なのか?」が明確なのです(`・ω・´) b

Kotlinプログラミング

Kotlinプログラミング

なにしろ、「クラス」が出てくるのが後半ってレベルでして、
高階関数をどのタイミングで使えばいいのか?」もわかるようになってます

この本でも一貫して貫かれていたのが「ベターJavaとしてのKotlin」であり、
その意味ではJavaを知らない人には少々難しくなりそうにも思えます

その点、題材を「ゲーム」にすることで敷居を下げており、
最後まで興味を持って読みやすく工夫されてます

正直、この本がなければ、今回の記事は書かなかったとというか、
インタプリタだけ書いて満足したと思います

訳本ではありますが、特に読みづらいところもなく、
コードの間違いが気になる以外は、全体としてよくできた本だと思います
Kotlinに興味がある方だけでなく、プログラム初心者にもお勧めです(´・ω・)っ

*1: 「ブラウザで動くLisp」を実装するつもりが、マーケティングの都合でJavaっぽくなってしまった・・・というのは有名な話ですね(´-ω-) でも、「関数を値として扱える」という本質を譲らなかったおかげで、柔軟性を備えているわけです(`・ω・´) b

*2: JavaScriptだって、初期には原始的なDOMの操作にしか使われてなかったのが、ブラウザの高速化により、今ではゲームすら動かせるわけですよね

*3: 最近は緩和されたようにも思いますが、それは裏に隠したってことであり、基本的には「型があるべき」という「設計思想」だと思います

*4: Rubyも今では独立した言語ですが、かつては「ベターなPerl」を意識していた時代があり、その名残が仕様の随所に見られます・・・が、だいぶ減りましたね

*5: C++が辛いから、もうちょっと書きやすくしつつ、今風のパラダイムを積極的に取り込んだ言語・・・ですよね?