クロージャにしてみる。

ということで、裸の配列を順に参照している部分を、クロージャにしてみようかと。
そもそも、配列をそのまま参照することが悪い訳では決して無いです。しかし、今回例示している様な簡単なイテレータならばそれでも良いですが、何やら複雑怪奇なメソッドだった場合には、配列をそのまま参照という単純な構造ではなく、手続きを内包するクロージャの様な概念を持ち込むことで解決できることがあるのではないか、という希望的観測に基づく実験的試みです。(遊んでいるだけとも言えるかもしれませんが……)

ただ、本来、私はテストコードはシンプルであるべき、と考えていますので、余り複雑なテストコードにはしたくありません。
それでも書いてみるというのは、やはり単なる遊びなのかもしれません。

さて、上のエントリで書いたテストコードを、そのままクロージャにしてみます。どんどん長くなってしまっているので一気に行きます。

$ cat test_iter_test.rb
require 'test/unit'
require 'iter_test'

class TC_DefineReader < Test::Unit::TestCase
  def setup
    # テストデータの配列を定義
    @test_data = [
      "* start line.\n",
      "# comment line.\n",
      "{ header start line.\n",
      "} header end line.\n",
      "/ separater line.\n",
      "[ block start line.\n",
      "] block end line.\n",
      "	 body line.\n",
    ];
    # イテレータに渡すパターンを定義
    @valid_regexp = /^[\{\}\[\]]/;     # valid.
    @invalid_regexp = /^[\{\}\[\]\s]/; # number of actuals more than expects.
  end

  def test_by_closure
    # クロージャを作ってアクセサとする方法。

    # テスト対象のオブジェクト生成
    obj = Iter_Test.new(@test_data);

    # 期待値を返すクロージャを生成するメソッドを定義。
    # 併せて「返した期待値のインデックス」を返すアクセサも返す。
    expects = [
      "{ header start line.\n",
      "} header end line.\n",
      "[ block start line.\n",
      "] block end line.\n",
    ];
    def make_expect expt
      i = 0;
      e = nil;
      [                         # 多値で返す。
        lambda {
          e = expt[i];
          i += 1;
          e;
        },
        lambda {
          i - 1;
        }
      ]
    end
    get_expect, get_num = make_expect(expects);

    # 期待値を順次取得してテストを実施。
    obj.get(@valid_regexp) { |l| # valid.
      assert_equal(get_expect.call, l,
                   "*** Error index: #{get_num.call}"); # 失敗時には添字を出力。
    };
    # 用意した全ての期待値について検証が行なわれたか。
    assert_nil(get_expect.call, "*** number of expects more than actuals.");
  end
end
$ ruby test_iter_test.rb
Loaded suite test_iter_test
Started
.
Finished in 0.177584 seconds.

1 tests, 5 assertions, 0 failures, 0 errors

となりました。

ミソは、二つのクロージャを生成しているところでしょうか。
先の配列直接参照のテストコードで、assert 失敗時に配列の添字を表示していることと同じことを行なうために、期待値を返すクロージャが直前に返却した期待値の添字を得るためだけのクロージャも生成しています。

配列を直接参照していたコードと比較して、面倒になってるだけな気がします……
まあ、冒頭に書いた様に、もっと複雑なデータ構造をテストする場合に、ひょっとしたら使えるかも……、くらいのものでしかないですかね。

クロージャとか言って、こんなことする位なら、普通にオブジェクト作れば良いだろ、というのは真っ当な意見だと思います。ということで、オブジェクトを生成するバージョンも書いてはあったんですが、もう長くなったので止めにします。クロージャ作るケースと代わり映えしませんしね。