Ruby嫌いがアンダースタンディングコンピュテーションを読んで

一番最初にはっきりさせておきますが、Rubyは嫌いな言語です。 が、この本はRubyが嫌いな自分でもいい本だと言える*1本でした。 自分が対象読者に入っているかどうかは実際に読んでみるまで微妙かな、と思っていましたが、とても楽しめました。 以下、書評です。

Rubyという選択

説明用のコードとして本書はRubyを使っていますが、 これに関してはその理由が1章にあります。

私はその明瞭さと柔軟さに魅かれてRubyを選びました

また、続けて

本書にはRuby独自の機能に依存しているところはありません。 そのため、もしあなたにとってわかりやすくなるなら、本書のサンプルコードをお好みの言語、特にPythonJavaScriptといった動的言語に変換してもよいでしょう。

とあります。

ここで注目すべきは「特にPythonJavaScriptといった動的言語」という風に、静的型付き言語を省いている(少なくとも積極的に推奨はしていない)点です。 で、これにはまっとうな理由がある(少なくとも自分は納得できる)のですが、この説明だけだとそれが全然わからないんですよね。 その理由をここに書いてしまうのは、ある意味この本を読む楽しさの一部を削いでしまうことになりかねない気もするのですが、そうなったとしてもこの本は依然として面白いであろうということで、書きます。 もちろん、「こういう理由があるからだ」という風に書きますが、すべて想像です。

対話環境があり、モンキーパッチングが可能であり、定数が削除できる

この本の素晴らしい点の一つに、実際に対話環境で一つ一つコードを入力していき、動作が確認できるというのがあります。 対話環境がない言語の場合はいちいち実行し直す必要があり、しかもこれまでに見てきた最早不要の出力(ようはゴミ)も表示されてしまいます。 面倒に思うかもしれませんが、きちんと理解したい方はRubyの環境を整えて*2、実際に対話環境でコードを入力して結果を確認しつつ読み進めるのがいいでしょう。

また対話環境前提で構成されているため、「以前定義したクラスのコードに戻ってこのメソッドを追加しましょう」ということができません。 そのため、モンキーパッチングができるような言語でないと実際に試しながら読むのはつらいです。

更には、「以前定義したクラスのコードに戻ってこの部分を書き換えましょう」もできません。 なので、定数を削除(というより、クラスを削除)できる必要があるのです。

もちろん、モンキーパッチングの代わりに別のモジュール内に既存のモジュールと同じものを定義してそれをopenするだとか、定数の削除の代わりにシャドウイングを使う等、このあたりはこの機能そのものがないと厳しいというわけではありません。

evalを持つ

eval的な、渡されたコードを実行する仕組みが欲しくなる場所があります。 本書で変換対象として挙げられていた言語(や、動的言語の多く?)は、eval的なものが用意されています。 これが気軽に使える言語でないと、evalを自分で実装・・・ということになりかねません。 すると当然のことながらすべてを本文に載せることは出来なくなり、本文のコードで試せないものができてしまいます。

もちろんこれにも回避方法はありますが、説明をシンプルに保つ、という点において本書がRubyのような言語を採用したのは正解だったと思います。

ちなみに、ここで挙げた理由を持つPythonJavaScriptが本書の言語として選ばれなかった理由としては、著者の好みもあるでしょうが、一番の理由はP.188からP.191な気がしています。

クラス分割の教材という観点

Rubyメタプログラミング的な技法などを使えば本書のコードはよりDRYに書けるでしょう。 ですが、それをすることなく一般的なOOPLで扱える程度の記述にとどめているため、他のOOPLでもクラス分割のひとつのお手本としてみることができます。

そういう観点でのオススメは3章です。 3章をすべてやると(正確には3.3まで)、基本的な機能をもった正規表現の処理系が手に入ります。 正規表現の処理系を「じゃぁ作って」と言われても、難しいと感じるプログラマは多いと思います。 3章では、それをボトムアップで作っていきます。 この際のクラスの分割方法や命名のセンスは素晴らしいです*3

3章の動機づけの弱さ

3章はコードは素晴らしいのですが、構成にもったいなさを感じました。 最終的には基本的な機能を持った正規表現の処理系が手に入るにもかかわらず、導入部分には

計算する機械というアイディアにある本質を明らかにし、それがどんな用途に使えるのか紹介しながら、単純なコンピュータにできることの制限について調べます。

としかないのです。 3章の最初の方はこの本の対象読者にとって「これが一体何に使えるんだ・・・」という感じの話が続きます。 人によっては退屈に感じて途中でやめてしまうかもしれません。 なので、個人的には最初の方に「この章では単純な例から始め、基本的な正規表現の処理系を作り、単純なコンピュータでも役に立つことを示します」くらいの人参をぶら下げた方がよかったのではないかな、と思います。

6章のバランス

この本は非常に内容の詰まった本であり、技術書の中ではページ数も少な目か普通程度のものです。 これだけの内容をこれだけ分かりやすくこれだけのページ数に収めているのは驚異的だと思うのですが、6章は少しアンバランスな気がしました。 もう数ページ増やして、リストの説明をより詳細に行ってもよかったのではないかな、と思うのです。 これまで丁寧に解説をしていたのに、リストでは解説なしに5つの関数が与えられてあとはその動作の確認にとどまっています。 本書のもったいないと思ったところで一番大きな部分が(言語の話ではなく)ここでした。

日本語としての読みやすさ

とても読みやすかったです。 「的」をあまり使わない方針なのか、一部ひっかかりを覚えた部分もありますが、好みの問題でしょう。 何か所か原文を確認したくなったところはありましたが、とても少ないです。 意味がよく分からないな、と思った個所は一つだけです。 P.169に、

ブール値を将来のコードが読める決まったデータとして考えるのではなく、2つの選択肢を引数として呼び出し、1番目と2番目の選択肢のどちらかを選ぶコードとして、直接的に実装しましょう。

とありますが、この前半部分の意味が分かりませんでした。 ただ、ここが分からなくても後半部分だけで実際にやりたいことはわかるため、それほど問題とも思いませんでした。

本書を読むために必要なレベル

人は自分がわかっていることに対してそのレベルを低く設定しがちな気がします。 「わかっている人にはわかる説明」というのはいくつもあり、分かってしまえばその説明で確かに十分だ、と思ってしまうことはそれなりにあります。

自分はある程度知識がある状態でこの本を読んでいるため、本書を読むために必要なレベルを本来よりも低く見積もってしまう可能性があります。 という言い訳を置いたうえで、この本を読むために必要なレベルはそこまで高くないと感じています。 ただし、最初の方にも書きましたが「実際にコードを試しながら読む」のを前提として、です。 逆に、実際に試さずに「難しかった」というのは、この本の読み方としては難易度の高い方法を選んだからかもしれませんよ?

汚れ?

P.210ページの右下付近、「partial」の「a」の上にななめ線が入っていました。 自分の周りの3冊を確認したところ、3冊すべてで入っていたので、多くの本で同じようなものが入っているでしょう。 内容には関係ない話なのでこれがあるからと言って本書の価値が下がるわけではありませんが。 むしろ、将来直った場合には自慢ポイントになるかも?

全体

全体を通して、「そういう説明をするのか、なるほど」と感じた個所が多い本でした。 これまで理解できていなかった部分が理解できるようになったり、新たな知識(薀蓄的なもの)が知れたりして勉強にもなりました。 Ruby嫌いは直りそうにありませんが、この本は好きになりました。

追記

サポートページはGithubなんですね。 そして、Issue 1に登録されていました。

次に読む本Wikiとしてまとめられているのも素晴らしいです。

*1:Rubyを使っているというだけですでにマイナスポイントからのスタートであるにも関わらず、いい評価

*2:好きな言語にコンバートしつつ、でもいいでしょうが、その場合でも本文を読み飛ばさずに進めた方が楽しいと思います。

*3:ただし、正規表現の処理系としてのクラス分割や名前付けが素晴らしい、という話ではないです