This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| tutorial:proceduraltype [2018/09/09 09:53] admin | tutorial:proceduraltype [2018/10/28 12:32] (current) admin | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| =====Procedural Type===== | =====Procedural Type===== | ||
| - | ====Procedural Type คืออะไร==== | + | =====Procedural Type คืออะไร===== | 
| - | คือ การสร้างตัวแปรชนิดที่เป็น procedure/function เพื่อให้สามารถนำไปใส่ใน input Argument ของ procedure/function อันอื่นได้ หรือเรียกอีกอย่างหนึ่งคือ การทำให้ procedure/function กลายเป็นตั่วแปร | + | คือ การสร้างตัวแปรชนิดที่เป็น procedure/function เพื่อให้สามารถนำไปใส่ใน input Argument ของ procedure/function อันอื่นได้ หรือเรียกอีกอย่างหนึ่งคือ การทำให้ procedure/function กลายเป็นตัวแปร | 
| + | \\ \\ | ||
| + | =====รูปแบบ===== | ||
| + | Procedural Type มีรูปแบบดังนี้ | ||
| + | ^ Topic ^ Format  ^ | ||
| + | |Type Declaration|<sxh delphi;> | ||
| + | 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 | ||
| + | </sxh> | | ||
| - | <hidden Example-1: Use a function as Input Argument> | + | <hidden Example-1: Function Finding Max Value> | 
| **ตัวอย่าง** การส่ง function เข้าไปอีก function หนึ่ง \\ | **ตัวอย่าง** การส่ง function เข้าไปอีก function หนึ่ง \\ | ||
| - | __ข้อสังเกต__: ปัญหาการส่งผ่าน func เข้าไปใน average_value ไม่สามารถทำได้ | + | __ข้อสังเกต__: การหาค่าสูงสุดของ function โดยการสร้าง function ที่มีชื่อว่า Find_Max จะสังเกตว่าภายใน function ดังกล่าว มีการเรียก function จากภายนอกเข้ามาคำนวณ ซึ่งเรียกว่า f() ดังนั้นเราจึงต้องกำหนดให้ f() เป็นตัวแปรชนิด Procedural Type\\ | 
| - | <sxh delphi;> | + | สำหรับ Lazarus การเรียก func เข้ามาใน Find_Max ในบรรทัดที่ 30 จะเป็นการเรียกผ่าน Pointer ดังนั้นจึงต้องใส่ @ นำหน้าชื่อ function เสมอ | 
| + | |||
| + | {{ :introduction:plot_polynomial.png?400 |}} | ||
| + | |||
| + | <sxh delphi;highlight: [4,13,30]> | ||
| + | PROGRAM Find_MaxValue_Of_Function; | ||
| + | |||
| + | TYPE | ||
| + | Tfunc = function(x:real):real; //Procedural Type | ||
| //define polynomial function f(x) = x^2+2*x-5 | //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; | function func(x:real):real; | ||
| begin | begin | ||
| - | result:=x*x+2*x-5 ; | + | result:=-x*x+10*x-10 ; | 
| end; | end; | ||
| - | //create function to find the average value between a and b of any function | + | function Find_Max(f:Tfunc; xFirst,xLast,increment:real):real; | 
| - | function average_value(a,b:real):real; | + | var x,xMax,max:real; | 
| begin | begin | ||
| - | result:=(a+b)/2; | + | x:=xFirst; | 
| + | xMax:=x; | ||
| + | max:= f(x); | ||
| + | while x<xLast do | ||
| + | begin | ||
| + | x:=x+increment; | ||
| + | if f(x)>max then xMax := x; | ||
| + | max:= f(x); | ||
| + | end; | ||
| + | result:=f(xMax); | ||
| end; | end; | ||
| - |  | + | |
| //Call the above function | //Call the above function | ||
| BEGIN | BEGIN | ||
| - | writeln(average_value(func(1),func(10))); | + | writeln('Max value between x = 0 to x = 10 is : ',Find_Max(@func,0,10,0.001)); | 
| readln; | readln; | ||
| END.  | END.  | ||
| </sxh>  | </sxh>  | ||
| </hidden> | </hidden> | ||
| - | ---- | + | \\ | 
| - | จาก Example-1 จะเห็นว่า เราไม่สามารถส่งตัวแปรที่เป็น procedure/function เข้าไปใน Argument ของ function average_value ได้ จึงจำเป็นต้องมีการประการ Type ของ function ก่อน ดังตัวอย่างต่อไปนี้ | + | ====ข้อแตกต่างระหว่าง Lazaus กับ Delphi ==== | 
| - | <hidden Example-2: แก้ปัญหาโดยการประกาศตัวแปร Procedural Type ก่อน > | + | ข้อสังเกต การใส่ function เข้าไปสำหรับ lazarus กับ delphi จะแตกต่างกัน โดย Lazarus จะใช้การส่งค่าผ่าน pointer ดังนั้นจึงต้องมีเครื่องหมาย @ นำหน้าชื่อ function แต่สำหรับ delphi สามารถส่งชื่อ function เข้าไปได้เลย ดูตัวอย่างที่ 2 | 
| - | <sxh delphi;> | + | |
| - | Type | + | <hidden Example-2: Function Finding Max Value (Delphi) > | 
| - | Tfunc = function(x:real):real;  | + | <sxh delphi;highlight: [3,32]> | 
| + | 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 | //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; | function func(x:real):real; | ||
| begin | begin | ||
| - | result:=x*x+2*x-5 ; | + | result:=-x*x+10*x-10 ; | 
| end; | end; | ||
| - | //create function to find the average value between a and b of any function | + | function Find_Max(f:Tfunc; xFirst,xLast,increment:real):real; | 
| - | function average_value(f:Tfunc; a,b:real):real; | + | var x,xMax,max:real; | 
| begin | begin | ||
| - | result:=(f(a)+f(b))/2; | + | x:=xFirst; | 
| + | xMax:=x; | ||
| + | max:= f(x); | ||
| + | while x<xLast do | ||
| + | begin | ||
| + | x:=x+increment; | ||
| + | if f(x)>max then xMax := x; | ||
| + | max:= f(x); | ||
| + | end; | ||
| + | result:=f(xMax); | ||
| end; | end; | ||
| - |  | + | |
| //Call the above function | //Call the above function | ||
| BEGIN | BEGIN | ||
| - | writeln(average_value(@func,1,10)); | + | writeln('Max value between x = 0 to x = 10 is : ',Find_Max(func,0,10,0.001)); | 
| - | + | readln; | |
| - | END. | + | END. | 
| </sxh>  | </sxh>  | ||
| </hidden> | </hidden> | ||
| ---- | ---- | ||
| - | ====ข้อแตกต่างระหว่าง Lazaus กับ Delphi ==== | + | =====Function of Object===== | 
| + | ตัวอย่างข้างบนนั้น ใช้ได้กับกรณีที่ function ถูกประกาศเป็น Global Scope เท่านั้น (จะสังเกตว่า func ไม่ได้อยู่ภายใต้ Class หรือ Object ใดๆ) ในกรณีที่ function ถูกประกาศเป็น Local Scope ภายใต้ Class หรือ Object ใดๆ จะต้องเปลี่ยนการประกาศ Type ใหม่เป็นดังนี้ | ||
| - | ข้อสังเกต การใส่ function เข้าไปสำหรับ lazarus กับ delphi จะแตกต่างกัน โดย Lazarus จะใช้การส่งค่าผ่าน pointer ดังนั้นจึงต้องมีเครื่องหมาย @ นำหน้าชื่อ function แต่สำหรับ delphi สามารถส่งชื่อ function เข้าไปได้เลย ดูตัวอย่างที่ 3 | + | Type | 
| + | TFunc = function(x:real):real of Object ; | ||
| - | <hidden Example-3: เปรียบเทียบการเรียก function โดย Lazarus กับ Delphi > | + | <hidden Example-3: Function of Object (TForm)> | 
| - | <sxh delphi;highlight: [19,22]> | + | **ตัวอย่าง** การประกาศ Procedural Type ของ function ที่ประกาศภายใต้ Form1\\ | 
| - | Type | + | __ข้อสังเกต__: การประกาศจะต้องมีคำว่า of object ต่อท้ายเสมอ  | 
| - | Tfunc = function(x:real):real; | + | <sxh delphi;highlight: [12]> | 
| + | unit Unit1; | ||
| - | //define polynomial function f(x) = x^2+2*x-5 | + | {$mode objfpc}{$H+} | 
| - | function func(x:real):real; | + | |
| + | 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 | begin | ||
| - | result:=x*x+2*x-5 ; | + | x:=xFirst; | 
| + | xMax:=x; | ||
| + | max:= f(x); | ||
| + | while x<xLast do | ||
| + | begin | ||
| + | x:=x+increment; | ||
| + | if f(x)>max then xMax := x; | ||
| + | max:= f(x); | ||
| + | end; | ||
| + | result:=f(xMax); | ||
| end; | end; | ||
| - | //create function to find the average value between a and b of any function | + | {$R *.lfm} | 
| - | function average_value(f:Tfunc; a,b:real):real; | + | |
| + | { TForm1 } | ||
| + | |||
| + | procedure TForm1.FormCreate(Sender: TObject); | ||
| begin | begin | ||
| - | result:=(f(a)+f(b))/2; | + | showmessage('Max value between x = 0 to x = 10 is : ' + | 
| + | FloatToStr(Find_Max(@func,0,10,0.001))); | ||
| end; | end; | ||
| - |  | ||
| - | //Call the above function | ||
| - | BEGIN | ||
| - | //Lazarus | ||
| - | writeln(average_value(@func,1,10));  | ||
| - |  | ||
| - | //Delhpi | ||
| - | writeln(average_value(func,1,10));  | ||
| - | END.  | + | function TForm1.func(x: real): real; | 
| + | begin | ||
| + | result:=-x*x+10*x-10 ; | ||
| + | end; | ||
| + | |||
| + | end. | ||
| + | |||
| </sxh>  | </sxh>  | ||
| </hidden> | </hidden> | ||
| + | ---- | ||
| + | =====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}  | ||
| + |  | ||
| + |  | ||