Twitterでクロージャのことを説明したら通じた

Twitterでクロージャのことを説明したらうまくいったのでメモ。

クロージャを語るときの関数は、構造化プログラミングの関数(サブルーチン)とちょっと違うんですよね。関数はcallメソッドを持ったオブジェクトというイメージ。関数を関数内で生成して変数として返せたりできる。

function joinWith(sep){
 return function(x){ return x.join(sep); };
}
joinWithComma = joinWith(",");
print(joinWithComma(data));

data.join(",") が何箇所も登場するプログラム書いてると、「そのカンマ、全角にして」とか言われたとき、変更箇所が増える。それを、joinWithCommaという関数にしとくとよくて、その関数を静的に定義するんじゃなくて、動的生成するの。

静的定義は joinWith(any) ひとつだけで済むから、似たような関数いっぱい作らなくていい。こういうプログラムがクロージャ使うと書けるようになります、ていうか、よく書きます。

ここまで。用途が見えると、理解しやすかったみたいです。

まあたしかに、OOPでも

class ArraySerializer {
  private String _sep;
  public ArraySerializer(String sep) {
    _sep = sep;
  }
  public String executeFor(List data) {
    return data.join(_sep); // えと、こんなのOKだったっけ??
  }
}
ArraySerializer commaSerializer = new ArraySerializer(",");
print(commaSerializer.executeFor(data));

っていうようなことはできるんだけど、そもそも、簡単にコードの冗長性を減らしたいという工夫のために逆にクラスを定義するとか... だったらもう grep するよ、ってなっちゃう。

モジュール設計を考えなくても、手続きから自然に文法を延長して書くレベルで、OOPの状態管理と同じかそれ以上に高度なことできるのが、高階関数がクロージャになる言語のいいところで、これこそコードの美化なのかなと思ったりします。