「Learning Functional Programming in Go」を読んだ

はじめに

Packt PublishingLearning Functional Programming in Go を読みました。

www.packtpub.com

この本は、Go で関数型プログラミングをやってみようというなかなかニッチな内容になっています。名前がアレなのでもしかしたら、Functional Programming in Scala みたいな内容を想像された方もいらっしゃると思いますが、確かに FP の重要性は伝えてくれるものの、言語の柔軟性を活かしたエレガントなコードを学ぶための本にはなっていないです。この本はどちらかというと「今の言語仕様つらい。じゃあどうするか」を学ぶための本です。

実はこの本を読み始めた当初は、err != nil をはじめとしたボイラープレートを排除して簡潔な記述を手に入れたいという願望がありました。それに対する解決策は一応書かれています。でも、どうも雰囲気が違うなというのは、Chapter1 を読んでいるときに気付きました。

この本が伝えようとしていること

では、この本で何が語られているかをざっくりと紹介しますね。

まず最初に、Go で FP をやるためには欠けているものがいくつかあります。一例を挙げると、

などです。

TCO がサポートされていないので、いくら再帰を末尾呼び出しで書いたとしてもコンパイラにガン無視され最適化してくれません。また、Generics が無いので関数を一般化することができずコピペの嵐となります。仮に interface{} で汎用的に処理しようとすれば今度はリフレクションやキャストなどの選択を迫られることになりパフォーマンス上問題になってしまいます。そう、どうあがいても命令型プログラミングとコピペという結末に収束してしまうのです。

だけど、Go には高階関数があるじゃないか!

ということで、以降は高階関数を使用した Functor、Monoid、Monad へと物語は進んで行きます。時折もし generics があったらなら、あんなことやこんなこともできるのにという著者の熱い想いに触れながら。

結局のところ、今の Go で FP をやるには色々妥協しなくちゃいけなくて、この本では「可能な限り関数型プログラミングスタイルを。必要に応じて命令型プログラミングスタイルを使用する」というスタンスで必死に抗い続けます。つらい。つらすぎる。

だが、そのつらさがオレに執念を与えた。だから、無かったことにするわけには行かなかったのだ。(岡部倫太郎)

その執念が、Go2 への活力となり、公式の Proposing Changes to Go で積極的に議論に参加するよう呼びかけています。

TCO だとこの辺。

github.com

generics だとこの辺ですか。

github.com

幸いにして、 Go 2 Draft Designs では、 generics の話が出てきているので、Go2 ではもう少し FP がやりやすくなるのかなと期待しています。

おわりに

この本はそれ以外にも SOLID原則やマイクロサービス、DDD、CQRS など、アーキテクチャレベルでのアプローチについても触れられていて、特に Go の Duck Typing 前提のデザインパターンは面白いなと思いました。また、Go2 に generics が入るのはメリットだけじゃなくてコンパイル時間が長くなるという懸念があることも触れています。それが今後どうなるのか注目したいところです。

個人的には、TCOgenerics もサポートされた Go2 で、改めて「Learning Functional Programming in Go 2」を出版していただきたいと思ってます。

追記(2018/08/31)

補足すると、本ではSOLID原則のことを紹介してますが、すべてが Go でできるわけじゃないので、例えばリスコフの置換原則について継承のない Go ではどう考えるかみたいな内容になっています。