表題の書籍について、出たとき(2015/5/29)に買って随分放置していたのだが、最近、一通り読んでみたので簡単な感想を書いてみようと思う。
結論からいうと、Scalaについて特に使う予定はないがおおまかにどんな言語か知っておきたいという方にはそこまで悪くない本だが、副題の「関数型プログラミングの設計と理解」について本書で学ぶのはオススメできない。そういう人には、Scala関数型デザイン&プログラミング ―Scalazコントリビューターによる関数型徹底ガイドをオススメしておこう。こっちの本も、ScalaでHaskellスタイルのFPをすることにこだわり過ぎて、Scala Wayからは外れていると感じる部分もあるのだが、少なくとも関数型プログラミングについて丁寧に取り組んでいるとはいえる。
本書を読む前に気になっていたのは、技術的な点での瑕疵がどの程度あるかということだったが、この点に関しては本書はまずまず合格点を上げられる出来と言っていい。Scalaの高度な機能についてあまり触れられていないという点に関しては不満が残るが、それは本書が目的としたところではなかろう。
技術的な正確さに関して気をつけていると思われることに関しては、たとえば以下のような記述(p.29)に現れている:
Scalaでは、メソッドはdefキーワードで定義されたものになります。また、メソッド以外のものを関数とし、この場合の関数は第一級オブジェクト(first-class object)としての性質を持つ関数、すなわち第一級関数(first-class function)と呼ばれるものです。
メソッドはdefキーワードで定義されたものになるというのは、自分がScalaにおけるメソッドと関数の区別として口を酸っぱくして言っていることなのだが、その辺りについてきちんと調べていることが伺える(偉そうだ)。
なお、本書で振れられていないScalaの重要な機能には以下のようなものがある:
次に、「関数型プログラミングの設計と理解」について、本書がどのようなアプローチをしているかというと…はっきり言ってウゲゲと思ってしまうものなのだ。一例を挙げよう。
本書では、名前渡しの機能を使って、制御構造を自作する例が多く取り上げられているのだが、その中で、ファイル書き込みの制御構造と題して次のようなメソッドfwloop
を定義している。
package ex.callbyname import java.io.File import java.io.FileWriter def fwloop (file: String, cond: => Boolean, update: => Unit)(body: => String) { var fw: FileWriter = null try { fw = new PrintWriter(new File(file)) while (cond) { fw.write(body) update } } catch { case e: Exception => println("Error: " + e.getMessage()) } finally { if (fw != null) { fw.close() } } }
fw
に初期値null
を代入してるがこれそもそも不要なんじゃという細かいツッコミはおいておく。問題は、このfwloop
メソッド、cond
, update
, body
がループのたびに変化することを前提にした設計になっており、関数型的な設計とは極めて相性が悪いという点である。このメソッドは次のように使うそうだ…
var a = data fwloop("dataout.txt", !a.isEmpty, a = a.tail) { a.head.mkString("\t") + "\r\n" }
本書の著者がここで何がやりたかったかというと、おそらく、名前渡しの機構を使って副作用を起こし、C言語風のforをエミュレートしたかったのだろうが、そんなことをScalaでやるべきではない!他にもいくつか例はあるが、この一例を見ただけで、本書から「関数型プログラミングの設計と理解」について学ぶのは絶望的だというのはわかったと思う。
本書で著者は、全体的に「頑張っている」のだが(このため、単純な事実誤認は少なくなっており、その点は単なる手抜き入門本と比べて良い部分だと思う)、それがどうも明後日の方向に向いているように感じる。
というわけで、本書は、あくまでScalaの言語機能のプチ紹介ツアーとして読むべきものであり、コード例から何かを学ぼうとしてはいけない。それはほぼ必ずScala Wayから外れていると言える。