=====Procedural Type===== =====Procedural Type คืออะไร===== คือ การสร้างตัวแปรชนิดที่เป็น procedure/function เพื่อให้สามารถนำไปใส่ใน input Argument ของ procedure/function อันอื่นได้ หรือเรียกอีกอย่างหนึ่งคือ การทำให้ procedure/function กลายเป็นตัวแปร \\ \\ =====รูปแบบ===== Procedural Type มีรูปแบบดังนี้ ^ Topic ^ Format ^ |Type Declaration| TYPE TFunc1 = function(x:integer):real; //for function 1-argument TFunc2 = function(x,y:integer):real; //for function 2-arguments TProc = procedure; //for procedure with no argument TProc1 = procedure(y:string); //for procedure 1-argument | **ตัวอย่าง** การส่ง function เข้าไปอีก function หนึ่ง \\ __ข้อสังเกต__: การหาค่าสูงสุดของ function โดยการสร้าง function ที่มีชื่อว่า Find_Max จะสังเกตว่าภายใน function ดังกล่าว มีการเรียก function จากภายนอกเข้ามาคำนวณ ซึ่งเรียกว่า f() ดังนั้นเราจึงต้องกำหนดให้ f() เป็นตัวแปรชนิด Procedural Type\\ สำหรับ Lazarus การเรียก func เข้ามาใน Find_Max ในบรรทัดที่ 30 จะเป็นการเรียกผ่าน Pointer ดังนั้นจึงต้องใส่ @ นำหน้าชื่อ function เสมอ {{ :introduction:plot_polynomial.png?400 |}} PROGRAM Find_MaxValue_Of_Function; TYPE Tfunc = function(x:real):real; //Procedural Type //define polynomial function f(x) = x^2+2*x-5 //This function has the Max value = 15 at x = 5 function func(x:real):real; begin result:=-x*x+10*x-10 ; end; function Find_Max(f:Tfunc; xFirst,xLast,increment:real):real; var x,xMax,max:real; begin x:=xFirst; xMax:=x; max:= f(x); while xmax then xMax := x; max:= f(x); end; result:=f(xMax); end; //Call the above function BEGIN writeln('Max value between x = 0 to x = 10 is : ',Find_Max(@func,0,10,0.001)); readln; END. \\ ====ข้อแตกต่างระหว่าง Lazaus กับ Delphi ==== ข้อสังเกต การใส่ function เข้าไปสำหรับ lazarus กับ delphi จะแตกต่างกัน โดย Lazarus จะใช้การส่งค่าผ่าน pointer ดังนั้นจึงต้องมีเครื่องหมาย @ นำหน้าชื่อ function แต่สำหรับ delphi สามารถส่งชื่อ function เข้าไปได้เลย ดูตัวอย่างที่ 2 PROGRAM Find_MaxValue_Of_Function; {$MODE delphi} TYPE Tfunc = function(x:real):real; //Procedural Type //define polynomial function f(x) = x^2+2*x-5 //This function has the Max value = 15 at x = 5 function func(x:real):real; begin result:=-x*x+10*x-10 ; end; function Find_Max(f:Tfunc; xFirst,xLast,increment:real):real; var x,xMax,max:real; begin x:=xFirst; xMax:=x; max:= f(x); while xmax then xMax := x; max:= f(x); end; result:=f(xMax); end; //Call the above function BEGIN writeln('Max value between x = 0 to x = 10 is : ',Find_Max(func,0,10,0.001)); readln; END. ---- =====Function of Object===== ตัวอย่างข้างบนนั้น ใช้ได้กับกรณีที่ function ถูกประกาศเป็น Global Scope เท่านั้น (จะสังเกตว่า func ไม่ได้อยู่ภายใต้ Class หรือ Object ใดๆ) ในกรณีที่ function ถูกประกาศเป็น Local Scope ภายใต้ Class หรือ Object ใดๆ จะต้องเปลี่ยนการประกาศ Type ใหม่เป็นดังนี้ Type TFunc = function(x:real):real of Object ; **ตัวอย่าง** การประกาศ Procedural Type ของ function ที่ประกาศภายใต้ Form1\\ __ข้อสังเกต__: การประกาศจะต้องมีคำว่า of object ต่อท้ายเสมอ unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs; type Tfunc = function(x:real):real of object; //Procedural Type { TForm1 } TForm1 = class(TForm) procedure FormCreate(Sender: TObject); private public function func(x:real):real; end; var Form1: TForm1; function Find_Max(f:Tfunc; xFirst,xLast,increment:real):real; implementation function Find_Max(f: Tfunc; xFirst, xLast, increment: real): real; var x,xMax,max:real; begin x:=xFirst; xMax:=x; max:= f(x); while xmax then xMax := x; max:= f(x); end; result:=f(xMax); end; {$R *.lfm} { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin showmessage('Max value between x = 0 to x = 10 is : ' + FloatToStr(Find_Max(@func,0,10,0.001))); end; function TForm1.func(x: real): real; begin result:=-x*x+10*x-10 ; end; end. ---- =====Function is Nested===== สำหรับการทำ Nested Function ให้กลายเป็น Procedural Type เพื่อส่งผ่านเป็นตัวแปรนั้น เราสามารถระบุ Function ดังกล่าวได้ตามนี้ Type TFunc = function(x:real):real is Nested ; จะสังเกตได้ว่าคล้ายกับการระบุ Function of Object นั่นเอง เพียงแต่เปลี่ยนจากคำว่า of Object เป็น is Nested แต่อย่างไรก็ตามสิ่งที่แตกต่างกันอีกอย่างหนึ่ง คือ คำสั่งข้างต้น จำเป็นต้องระบุ Compiler Directive ดังนี้ก่อนเสมอ {$modeswitch nestedprocvars}