Swanman's Horizon

性欲をもてあましつつなんらかの話をするよ。

無名メソッドをその場で呼び出す。

無名メソッドは変数に代入したり、関数に渡して使うものだから、その場で呼び出しちゃうってことは一度きりの使い捨て?再利用できなくね?何の意味があるの?という疑問をお持ちの方もいるかもしれないけど、例えばクロージャを作りたい場合なんかは「クロージャを返す関数(エンクロージャ)」をその場で呼び出したかったりするよね。たぶん。
で、そんな時はキャストすればOK。

function CreatePokoProcs: TList<TProc>;
var
  c: Char;
begin
  Result := TList<TProc>.Create;
  for c := 'は' to 'ぽ' do
  begin
    Result.Add(
      TFunc<TProc>(function: TProc // TFunc<TProc>でキャスト
      var
        po: Char;
      begin
        po := c;
        Result := procedure
          begin
            Writeln(po+'こたんインしたお!');
          end;
      end)()
    );
  end;
end;

var
  list: TList<TProc>;
  proc: TProc;
begin
  list := CreatePokoProcs;
  for proc in list do
    proc();
  list.Free;
end;
結果
> はこたんインしたお!
> ばこたんインしたお!
> ぱこたんインしたお!
(..中略..)
> ほこたんインしたお!
> ぼこたんインしたお!
> ぽこたんインしたお!

JavaScript的な感覚だとカッコで囲ってさえあれば呼び出せそうなんだけど、

(procedure
begin
  // こんな風に
end)();

キャスト用の型を取り去るとコンパイルは通るのに実行時にエラー。これって地味にバグな気がするんだけどどうなんだろう…コンパイル時じゃなくて実行時にエラーになるってところも怪しいし。
実際、いちいちキャストするのは面倒なんだよね。今回はTFuncやTProcなんてので済んでるからいいけど、引数のある関数を返そうとするとTFunc>みたいにどんどん長くなるし、TProcみたいな既存の定義が使えないような場合は、あらかじめreference toで定義作っておかないといけないし。

まぁエンクロージャに限れば、無名メソッドを使うより今まで使ってきた関数内関数さんを使ってあげた方がスマートかも。

function CreateOisuProcs: TList<TProc>;
var
  c: Char;

  function CreateOisuProc: TProc;
  var
    po: Char;
  begin
    po := c;
    Result := procedure
      begin
        Writeln(po+'こたん「おいすー^^」');
      end;
  end;
begin
  Result := TList<TProc>.Create;
  for c := 'は' to 'ぽ' do
  begin
    Result.Add(CreateOisuProc());
  end;
end;