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