======Procedure and Function======
=====Procedure/Function คืออะไร=====
ทั้งคู่ทำหน้าที่เป็นโปรแกรมย่อยเหมือนกัน แต่มีความแตกต่างกันอยู่ดังนี้
* Function จะส่งค่ากลับ
* Procedure ไม่ส่งค่าใดๆกลับ
\\
=====รูปแบบของ Procedure=====
Procedure โดยปกติจะมีอยู่ 2 แบบ คือ แบบรับค่า input กับแบบไม่รับค่า input\\
^ Topic ^ Format ^
|Procedure แบบไม่รับค่า Input|
procedure ProcedureName;
begin
{Do something}
end;
|
|Procedure แบบรับค่า Input|
procedure ProcedureName(Arg1,Arg2:integer; Arg3:real);
begin
{Do something}
end;
|
procedure SayHelloWorld;
begin
writeln('HelloWorld');
end;
procedure SayHello(Name,SurName:string; Age:integer);
begin
writeln('Hello ',Name,' ',Surname);
writeln('Your age is ',Age);
end;
\\ \\
=====รูปแบบของ Function=====
รูปแบบของ function นั้น จะคล้ายกับ procedure ทุกประการ คือมีทั้งแบบรับค่า input กับแบบไม่รับค่า input\\
แต่โดยทั่วไปแล้ว function มักจะถูกใช้งานโดยการรับค่า input (เพราะถ้าไม่มีการรับค่า ก็ไม่ต่างจากการใช้ค่าคงที่)\\
อย่างไรก็ตาม สิ่งที่ขาดไม่ได้เลยสำหรับการประกาศ function คือ ต้องมีการส่งค่า output กลับด้วยเสมอ\\
ตัวแปรที่ใช้รับค่าเพื่อแสดงค่า output มีได้ 2 แบบ คือ
^ Topic ^ Format ^
|Function แบบใช้ตัวแปรที่ชื่อ result เป็น Output|
function FunctionName(Arg1,Arg2:integer; Arg3:real):integer;
begin
result:= {Do something};
end;
|
|Function แบบใช้ตัวแปรที่เป็นชื่อของฟังก์ชั่นเอง เป็น Output|
function FunctionName(Arg1,Arg2:integer; Arg3:real):integer;
begin
FunctionName:= {Do something};
end;
|
function multiply(a,b:real):real;
begin
result:=a*b;
end;
function multiply(a,b:real):real;
begin
multiply:=a*b;
end;
\\
จากประสบการณ์ของผม ขอแนะนำให้ใช้ result แทนชื่อของ Function ครับ เพราะจะง่ายในการแก้ใขชื่อ Function ในภายหลัง
\\ \\
=====การประกาศและการเรียกใช้ Procedure/Function=====
หลังจากการประกาศ uses แล้ว Procedure/Function ที่เป็น Global Scope สามารถประกาศไว้ ณ ส่วนไหนของโปรแกรมก็ได้ แต่โดยปกติแล้ว ผมขอแนะนำให้ประกาศทีหลังสุด (หลังจากประกาศ var) แต่ถ้าหากเป็น Function/Procedure ที่มาจาก Shared Library ผมขอแนะนำให้วางไว้แรกสุด (ต่อจากการประกาศ uses) \\
การเรียกใช้ Procedure นั้นง่ายมาก เพียงแค่ใส่ชื่อ Procedure นั้นๆ (พร้อมกับ Input Parameters ถ้ามี) ได้เลย ยกตัวอย่างเช่น
Program SayHellow;
procedure HelloWorld;
begin
writeln('HelloWorld');
end;
procedure SayHello(sName:string);
begin
writeln('Hello'+ sName);
end;
Begin
HelloWorld; //Calling HelloWorld
SayHello('Mr. Smith'); //Calling Procedure
End.
\\
สำหรับการเรียกใช้ Function นั้นก็คล้ายกับการเรียกใช้ Procedure แต่มีข้อแตกต่างอีกอย่างหนึ่ง คือ Function ให้ค่า Output ด้วย
\\ \\
=====Nested Function/Procedure=====
คือ Function/Procedure ที่เป็น Local Scope ซ้อนอยู่ใน Function/Procedure อื่น\\
procedure SolvePolynomial(A,B,C:real);
//This function used for solving polynomial Ax^2+Bx+C = 0
var Ans1,Ans2:real;
function IsReal(A,B,C:real):Boolean; //Nested Function
begin
if (B*B-4*A*C)>= 0 then
result:=true
else
result:=false;
end;
begin
if IsReal(A,B,C) then
begin
Ans1:=(-B+power(B*B-4*A*C,0.5))/(2*A);
Ans2:=(-B-power(B*B-4*A*C,0.5))/(2*A);
writeln('x1 = ', Ans1);
writeln('x2 = ', Ans2);
end
else
writeln('x1 = '+ FloatToStr(-B/(2*A))+' + '+ FloatToStr(power((B*B-4*A*C)*(-1),0.5)/(2*A))+'i');
writeln('x2 = '+ FloatToStr(-B/(2*A))+' - '+ FloatToStr(power((B*B-4*A*C)*(-1),0.5)/(2*A))+'i');
//function Power() requires unit: math
//function FloatToStr() requires unit: SysUtils
end;
\\ \\
=====Passing Parameters=====
การส่งผ่าน Parameters เข้าไปใน Procedure/Function มี 2 แบบ คือ By Value และ By Reference
* **By Value** คือ ส่งเฉพาะค่าของ Parameter เข้าไปใน Procedure/Function โดยหากมีการเปลี่ยนแปลงค่าใดๆใน Procedure/Function นั้น จะ__**ไม่เปลี่ยนแปลง**__ต่อค่าที่แท้จริงของ Parameter สำหรับการรับค่าแบบปกติ
* **By Reference** คือ หากมีการเปลี่ยนแปลงค่าใดๆของ Parameter ใน Procedure/Function นั้น จะ__**เปลี่ยนแปลง**__ค่าที่แท้จริงของ Parameter ด้วย
====By Value====
การใส่ตัวแปรแบบทั่วไป คือ การส่งผ่าน Parameter ในแบบ By Value
procedure DoItA(X:integer);
begin
X:=10;
writeln('X = ',X);
end;
====By Reference====
เราสามารถใส่ var หน้า Parameter เพื่อให้กลายเป็น By Reference ได้ดังนี้
procedure DoItB(var X:integer);
begin
X:=10;
writeln('X = ',X);
end;
program Passing_Param;
var A,B:integer;
procedure DoItA(X:integer); //By Value
begin
X:=100;
writeln('DoItA, X = ',X);
end;
procedure DoItB(var X:integer); //By Reference
begin
X:=200;
writeln('DoItB, X = ',X);
end;
begin
A:=1;
B:=2;
writeln('A = ',A);
writeln('B = ',B);
DoItA(A);
DoItB(B);
writeln('A = ',A);
writeln('B = ',B);
readln();
end.
Compiled Results:
A = 1
B = 2
DoItA, X = 100
DoItB, X = 200
A = 1
B = 200
\\
=====Forward Declaration=====
คือ การประกาศ Procedure/Function ล่วงหน้าเพื่อให้ทุก Procedure/Function สามารถเรียกใช้งานกันและกันได้หมด สาเหตุที่ต้องทำแบบนี้เพราะว่า โดยปกตินั้น Compiler จะอ่าน source code จาก บนลงล่าง ดังนั้น หากมี Procedure/Function ตัวใดตัวหนึ่งเรียกใช้งาน Procedure/Function ตัวอื่นที่ยังไม่ได้ประกาศ จะทำให้เกิด Error \\
รูปแบบการประกาศสำหรับ Program จะมีคำว่า forward ต่อท้ายดังนี้
Procedure DoSomething; forward;
สำหรับ Unit นั้น FPC บังคับให้ต้องมีการทำ forward declaration ทุกครั้งก่อนเสมอ เพราะ unit อื่นหรือ program ที่มีการ uses unit ดังกล่าวนั้น จะเข้าถึง Procedure/Function ได้เฉพาะส่วนที่เป็น interface เท่านั้น ไม่สามารถเข้าถึงส่วน implementation โดยตรงได้ ดังนั้นจึงต้องประกาศล่วงหน้าในตำแหน่งใต้คำว่า interface เสมอ โดยการประกาศจะไม่มีคำว่า forward ต่อท้ายเหมือนของ program อีก ดังตัวอย่างต่อไปนี้
unit Unit1;
interface
//Forward declaration
procedure First;
procedure Second;
implementation
procedure First;
begin
writeln('Hello First');
Second;
end;
procedure Second;
begin
writeln('Hello Second');
end;
end.
\\
__**อธิบาย**__ - ตัวอย่างนี้ มีการประกาศโปรแกรมย่อย ชื่อ Second ล่วงหน้าในบรรทัดที่ 4 เพื่อให้โปรแกรมย่อยที่ชื่อ First ได้รู้จัก Second ก่อน แน่นอนว่าหากตัด code ในบรรทัดที่ 4 ออกไปแล้ว สิ่งที่จะตามมาคือ เมื่อ compiler อ่านจนมาถึง First ก็จะฟ้องทันทีว่าไม่สามารถหา Second เจอ
program FWD_Declaration;
//Forward declarations
procedure Second; forward;
//Implementations
procedure First;
begin
writeln('Hello First');
Second;
end;
procedure Second;
begin
writeln('Hello Second');
end;
begin
First;
readln();
end.
Compiled Results:
Hello First
Hello Second
\\