(ちょっと前のことになりますが)札幌ドームに向かう車中で、無名内部クラスの new にはクラスだけではなく、インターフェイスも使える(おおっ!…と一瞬、思ったけど、まあしくみを考えてみれば当たり前で、むしろ使えないほうがおかしいんですが)ということを バスケさんに教わったので、改めてもう一回 Java の無名クラスとクロージャの関係について考えてみました。
public class RunnableAnonymous { public static void main(String[] args) { Runnable block = new Runnable() { public void run() { System.out.println("ah?"); } }; block.run(); } }
こんなんで aBlock value みたいな感じが出てますかね。ここで Runnable の代わりになる“Block”インターフェイスを作るのが(引数や返り値のことを考えると)大変そうですが、まあ、クロージャは無名内部クラスで事足りるという Java 者の気持ちは分かったような。
Smalltalk のクロージャは(Squeak のブロックはクローズしていないのでなんなのですが…)、通常の手続きを [ ] で括るだけなので、lambda とか Proc.new とかがいらないぶん、シンプルで使い勝手がよくて好きです。(もちろん [ ] で括るほかにも、当然、ブロック変数の宣言文は添えないといけませんが、まあ、これは一時変数の宣言文の延長みたいなものなので…)
counterMaker counter1 counter2 |
これが Ruby だとこんなかんじ。
counter_maker = Proc.new {| count | Proc.new {count += 1}} counter1 = counter_maker.call(0) counter2 = counter_maker.call(100) 10.times {printf "%#5d%#5d\n", counter1.call, counter2.call}
はるかに短いじゃん。orz いや、まあ、自己代入とか、一時変数の宣言不要とか、メソッド名の短さが効いてますけどね。さらに変数名とか Ruby 風にすればもっと短くなるので、Proc.new の存在なんて誤差の範囲、という意見も聞こえそうですが(笑)。ちなみに Rubyist 向けに余談ですが、Ruby の {| 変数 | ...} は、Smalltalk の [:変数 | ...] に相当していて、 Smalltalk の | 変数 | とは(見た目似ていますが)また違うものです。(Ruby は一時変数の宣言が不要なので Smalltalk の | 変数 | に相当するものはありません)
結果は、ちゃんとクローズしていればこうなります。
"VW, Ruby: => 1 101 2 102 3 103 4 104 5 105 6 106 7 107 8 108 9 109 10 110"
"Squeak: => 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120"