クロージャ
なんか、気分を害させてしまったようで、申し訳ない。そういうつもりではなかったのだけれど。
言い訳させてもらうと、「クロージャは、可読性を下げるので、小さくするべきだ」という命題が、どう考えても論理的に意味のある命題になっていないように感じたので、クロージャの意味を取り違えているのだろうと思ったのです。(むしろ、クロージャでない方が、可読性を下げると思いますし)
で、クロージャのことを、他でもよく見かけた「無名関数のことと誤解する」パターンなのかなと考えて、「無名関数は、可読性を下げるので、小さくするべきだ」と読み替えると意味が通るので、そのように誤解したのでした。(それだけでなく、コメントでのやりとりや「記述が簡単というのがクロージャ本質」というような表現からも、そのような誤解を促進した面はあります)
しかし、クロージャを無名関数と取り違えていないなら、どうして「クロージャは、可読性を下げるので、小さくするべきだ」と考えるようになったのか、また興味はありますが、これについては、ひとまずおしまいにしておきます。
Javaのクロージャ
ところで、Javaでクロージャ(ローカルクラス)を使うときのfinal修飾子が邪魔に感じていたのは、基本型がボックス化されていない点もあるのかな、と思ったりしました。もし副作用が欲しければ、何かしらの方法でボックス化してやれば、得ることは可能だ。
import java.util.concurrent.atomic.AtomicInteger; public class CounterMaker { static Closure mkCounter() { final AtomicInteger count = new AtomicInteger(0); return new Closure() { public int get() { return count.getAndAdd(1); } }; } } interface Closure{ int get(); }
それから、次のように書けば、final修飾子の制限も実質的に気にしなくてもよいかも。
public class AdderMaker { static Closure mkAdder(final int _m) { return new Closure() { int m = _m; public int add(int n) { m += n; return m;} }; } } interface Closure { int add(int n); }
id:sumimさん
Smalltalkのブロックがもともとクロージャでなかったというのは、興味深いですね。
それはそうと、この先は私見なのですが、Smalltalkは「コードもオブジェクトだ」という発想が根底にあるんじゃないでしょうか。だから、コードのかたまりであるブロックがオブジェクトであることは自然な帰結なのではないかと思います。(ちょうど、Lispが「手続きもS式だ」という発想から、lambda式やマクロの存在が自然な帰結であるように。)また、ブロックがwhileTrueやifTrueなどのメソッドを持つことも、そういう発想からなのではないかなと思っています。
それに対して、「コードはコードであり、オブジェクトではない」という発想に立てば、ブロックを許容するのは論理的におかしいということは納得できます。特に、オブジェクト指向では、関数が存在せず、全ての手続きはオブジェクトのメソッドであることを考えれば、関数オブジェクトに対して強い拒否を示すのは当然ではないかと思います。
このように考えると、ブロックを許容するかは、「メッセージベース」か「クラスベース」かという観点よりも、コードをオブジェクトとして見るかどうかという観点から読み解く方が、よいかもしれません。
また、その流れで言えば、Javaのローカルクラスや無名クラスというアイデアは、コードをオブジェクトとみなさないタイプで純血のオブジェクト指向において、クロージャを実現するための、必然的な帰結なのではないかと考えています。(そういう意味で、ローカルクラスを非オブジェクト指向的に感じる人がいるかもしれませんが、私はむしろ、非常に純粋なオブジェクト指向的な発想ではないかと思っています)