2009年4月12日日曜日

僕の使っている言語でもできるんです。(その1)

遅ればせながら『More Joel On Software』をよんでいます。

そのなかで、「君のプログラミング言語で、これ、できる?」と
題して、無名関数をあつかっていたのでDelphi2009で書いてみました。
今回はその前半部分です。

話の流れは、『More Joel On Software』を参照にしてください。

まづは、関数を使わない例

0001 program Project1;

0002

0003 {$APPTYPE CONSOLE}

0004

0005 uses

0006   SysUtils;

0007

0008 begin

0009   try

0010   { TODO -oUser -cConsole Main : ここにコードを記述してください }

0011   WriteLn('スパゲッティが食べたい!');

0012   WriteLn('チョコレートムースが食べたい!');

0013   except

0014     on E:Exception do

0015       Writeln(E.Classname, ': ', E.Message);

0016   end;

0017 end.

0018

0019



食べたいが一緒だから関数化して

0001 program Project2;

0002

0003 {$APPTYPE CONSOLE}

0004

0005 uses

0006   SysUtils;

0007

0008 procedure SwedishChef(food : string);

0009 begin

0010   WriteLn(food + 'が食べたい');

0011 end;

0012

0013 begin

0014   try

0015   { TODO -oUser -cConsole Main : ここにコードを記述してください }

0016     SwedishChef('スパゲッティ');

0017     SwedishChef('チョコレートムース');

0018   except

0019     on E:Exception do

0020       Writeln(E.Classname, ': ', E.Message);

0021   end;

0022 end.

0023

0024



ここまでは、今までのDelphiでも可能です。

従来の手続き型で呼び出す関数を切り替えて

0001 program Project3_1;

0002

0003 {$APPTYPE CONSOLE}

0004

0005 uses

0006   SysUtils;

0007

0008 Type

0009   TTakeSometingProc = procedure( S : String);

0010

0011 procedure PutInPot(food : string);

0012 begin

0013   Writeln(food);

0014 end;

0015

0016 procedure BoomBoom(food : string);

0017 begin

0018     Writeln(food);

0019 end;

0020

0021 procedure Cook(food1,food2 : String; aTakeSometingProc : TTakeSometingProc);

0022 begin

0023   Writeln(food1 + 'を取る');

0024   aTakeSometingProc(food1);

0025   aTakeSometingProc(food2);

0026 end;

0027

0028 begin

0029   try

0030   { TODO -oUser -cConsole Main : ここにコードを記述してください }

0031     Cook('ロブスター','水',PutInPot);

0032     Cook('チキン','ココナッツ',BoomBoom);

0033   except

0034     on E:Exception do

0035       Writeln(E.Classname, ': ', E.Message);

0036   end;

0037 end.

0038



これも問題なくうごきます。

手続き型を無名メソッドの宣言に書き換えて

0001 program Project3_2;

0002

0003 {$APPTYPE CONSOLE}

0004

0005 uses

0006   SysUtils;

0007

0008 Type

0009   TTakeSometingProc = reference to procedure ( s : String);

0010

0011

0012 procedure PutInPot(food : string);

0013 begin

0014   Writeln(food);

0015 end;

0016

0017 procedure BoomBoom(food : string);

0018 begin

0019     Writeln(food);

0020 end;

0021

0022 procedure Cook(food1,food2 : String; aTakeSometingProc : TTakeSometingProc);

0023 begin

0024   Writeln(food1 + 'を取る');

0025   aTakeSometingProc(food1);

0026   aTakeSometingProc(food1);

0027 end;

0028

0029 begin

0030   try

0031   { TODO -oUser -cConsole Main : ここにコードを記述してください }

0032     Cook('ロブスター','水',PutInPot);

0033     Cook('チキン','ココナッツ',BoomBoom);

0034   except

0035     on E:Exception do

0036       Writeln(E.Classname, ': ', E.Message);

0037   end;

0038 end.

0039



手続き型の仮引数に対する本引数をコードブロックにすると

0001 program Project4_1;

0002

0003 {$APPTYPE CONSOLE}

0004

0005 uses

0006   SysUtils;

0007

0008 Type

0009   TTakeSometingProc = procedure( S : String);

0010

0011 procedure PutInPot(food : string);

0012 begin

0013   Writeln(food);

0014 end;

0015

0016 procedure BoomBoom(food : string);

0017 begin

0018     Writeln(food);

0019 end;

0020

0021 procedure Cook(food1,food2 : String; aTakeSometingProc : TTakeSometingProc);

0022 begin

0023   Writeln(food1 + 'を取る');

0024   aTakeSometingProc(food1);

0025   aTakeSometingProc(food2);

0026 end;

0027

0028 begin

0029   try

0030   { TODO -oUser -cConsole Main : ここにコードを記述してください }

0031     Cook('ロブスター','水',PutInPot);

0032     Cook('チキン','ココナッツ',BoomBoom);

0033   except

0034     on E:Exception do

0035       Writeln(E.Classname, ': ', E.Message);

0036   end;

0037 end.



これは、コンパイルエラーになります。



無名メソッド型を使えば、コンパイルがとおります。

0001 program Project4_2;

0002

0003 {$APPTYPE CONSOLE}

0004

0005 uses

0006   SysUtils;

0007

0008 Type

0009   TTakeSometingProc = reference to procedure ( s : String);

0010

0011

0012 procedure Cook(food1,food2 : String; aTakeSometingProc : TTakeSometingProc);

0013 begin

0014   Writeln(food1 + 'を取る');

0015   aTakeSometingProc(food1);

0016   aTakeSometingProc(food2);

0017 end;

0018

0019 begin

0020   try

0021   { TODO -oUser -cConsole Main : ここにコードを記述してください }

0022     Cook('ロブスター','水',procedure(food : string)

0023                           begin

0024                             WriteLn(food + 'を鍋に入れる');

0025                           end

0026                           );

0027     Cook('チキン','ココナッツ',procedure(food : string)

0028                             begin

0029                               WriteLn(food + 'を撃つ');

0030                             end

0031                           );

0032   except

0033     on E:Exception do

0034       Writeln(E.Classname, ': ', E.Message);

0035   end;

0036 end.

0037

0 件のコメント: