=====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}