著作一覧 |
木村さんのところでなんか読んだほうが良さそうなことが書いてあったので、アマゾンを見てみると、こないだ草葉の蔭に思いが飛んでしまった草思社なもんですでに新刊は存在しない(リアル書店だと在庫があるんじゃないかって気もするけど)。とはいえ、マーケットプレイスに定価で出品されてたんで、注文した。
思考する機械コンピュータ (サイエンス・マスターズ)(ダニエル ヒリス)で、さっそく読み始めたのが3日前くらい。
おお、目からうろこがそれなりに落ちてくるではないか。言葉というのはまさに使い方だな、とそのあたりも含めて、なるほど、これは読む価値があるようだ(いま、プログラミング言語に入ったところで、これまでのところは)。
僕は、アセンブラのようなものから入ったから、レジスタとかポインタとかスタックとかそういうものについては頭の中でいくらでも操作できる。そのため、コンピュータについて「低レベル」という言葉の意味をそのあたりにおかれているのを見ると、なんとなく違和感を覚えるのだが(っていうのは、これはやはり実装の詳細に過ぎないと思うのだ。というのも、使っていたのは非スタックマシンでスタックは存在しなかったわけだけど、スタックマシンを使うようになったからといって理解の断絶がなかったからだ。ということは、より下により抽象化できる層があるということではないだろうか)、この本では最初に論理回路がきて、その上に有限状態機械が置かれていた。これは、すごくしっくりときたよ。
(たまたま、2か月前くらいにとある事情からえらくへたくそな3目並べのアルゴリズムを作った(失敗しているのだがそれはそれ)という事情もあって、この本の掴みが3目並べだったので妙に引き付けられたという側面もあるかも。しかも別件でじゃんけん勝敗マシンのプログラムを作り上げた直後に、読み始めた章にじゃんけんマシンが次の掴みとして入っていたり。おかげで、僕もそれほど思考の方向性は外していないかも知れないかも知れないとか思ったりもしたわけだが、入口は1つでも中はたくさんあるからこれも別問題だ)
ところどころに問題が入っている。
最初の問題は、解けた今となっては、見た瞬間にわかりそうなものに感じるけど、実際には1日かかった。それだけ、そのレイヤで思考する習慣がないということなのだろう。
AND回路とINVERT回路を使って、OR回路と等価な論理ブロックを組み立てる方法は?
数秒で解けなかった場合は、この問題を次のように置き換えてみてやってみれば良いかも。
require 'test/unit' def _and(x, y) x && y end def _invert(x) !x end #以下を満たす_or関数の中を埋めよ def _or(x, y) ? end class TestOr < Test::Unit::TestCase def test_or assert_equal true, _or(true, true) assert_equal true, _or(true, false) assert_equal true, _or(false, true) assert_equal false, _or(false, false) end endで、この結果が、OR回路とINVERT回路を使ってAND回路を組み立てた型(これは最初のほうで示されている)ときれいな相似形で、ちょっと感動したり。
ばかなバグで、テストプログラムが間違っている(少なくとも正しく機能しない)場合には、役に立たないという話。
Rjbのテストに以下のメソッドがある。
def test_field() point = import('java.awt.Point') pnt = point.new(11, 13) assert_equal(11, pnt.x) assert_equal(13, pnt.y) pnt.x = 32 assert_equal(32, pnt.x) end
このメソッドは、フィールドアクセスのテストで、そのため、あの悪名高いPointクラスを利用している。
1.0.5で、jruby同様のRuby化したメソッド/アクセサを取り込んだ。その時点でバグが混入してフィールドの読み込みアクセスはできなくなってしまった(書き込みは可能)。でも、上記のテストの表明は問題なし。というのは、
def test_field() point = import('java.awt.Point') pnt = point.new(11, 13) assert_equal(11, pnt.x) # pnt.getX() のRuby化メソッド呼び出し assert_equal(13, pnt.y) # pnt.getY() のRuby化メソッド呼び出し pnt.x = 32 # ここはフィールドへ設定できる assert_equal(32, pnt.x) # pnt.getX() のRuby化メソッド呼び出し end
となったからだ。だから、Pointクラスではなく、ゲッタセッタを持たないか、または名前がフィールドと衝突しない公開フィールドのみを持つクラスを使うようにテストを変える必要があったのであった。
でも、これはフィールド公開インターフェイスを選択したのに、無意味なゲッタメソッドを後(1.2)から追加したPointクラスのインターフェイスがまずいのだと思う。(イミュータブルにすべきとかいろいろ考えはあるだろうが、Pointは限りなくプリミティブだと思うので、フィールドアクセスは別に構わない)。
ジェズイットを見習え |