Java の無名内部クラスとクロージャ

(ちょっと前のことになりますが)札幌ドームに向かう車中で、無名内部クラスの 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
counterMaker := [: initialValue | | count | count := initialValue. [count := count + 1]]. counter1 := counterMaker value: 0. counter2 := counterMaker value: 100. "ActiveWorld findATranscript: ActiveEvent." "for Squeak" 10 timesRepeat: [ Transcript cr; show: counter1 value printString. Transcript tab; show: counter2 value printString]

これが 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 みたいにクロージャじゃないと…。

"Squeak: =>
101	102
103	104
105	106
107	108
109	110
111	112
113	114
115	116
117	118
119	120"