Difference between revisions of "Function"

From Lazarus wiki
Jump to navigationJump to search
(review)
Line 1: Line 1:
 
{{Function}}
 
{{Function}}
== Overview ==
 
A '''function''' is a declaration of a [[Routine|routine]] which may be invoked
 
* from within the [[Unit|unit]] that declares it
 
* from outside the unit if the function is public,
 
* or from within a [[Program|program]]
 
  
The routine returns a value as part of its definition.  A routine that does not return a value as part of its definition is a ''[[Procedure|procedure]]''.  
+
A '''function''' is a [[Routine|routine]] that, in contrast to [[Procedure|procedures]], returns a value.
 +
A call of a function is virtually substituted by its return value.
 +
Depending on the [[sExtendedsyntax|<syntaxhighlight lang="pascal" enclose="none">{$extendedSyntax}</syntaxhighlight> compiler switch]] state, non-productive statements involving a function call are allowed or not.
  
A function which is part of an object is called a [[Property|property]] and can be assigned/return a value (if you can't assign a value, it would be a [[Method|method]])
+
The word <syntaxhighlight lang="pascal" enclose="none">function</syntaxhighlight> is a [[Reserved word|reserved word]].
  
== Function  parameters ==
+
== return value ==
 +
In addition to a normal procedure, a function's formal signature contains a return type:
 +
The formal parameter list has to be succeeded by a colon and return type.
 +
For instance the following function returns a [[Boolean|<syntaxhighlight lang="pascal" enclose="none">boolean</syntaxhighlight>]].
 +
<syntaxhighlight lang="pascal">
 +
function myFunction(const firstParameter: real): boolean;
 +
</syntaxhighlight>
  
* Call by value
+
When implementing functions there are several ways to define the function's return value.
* [[Variable parameter]] (call by reference)
+
<syntaxhighlight lang="pascal" line>
* Out parameter
+
program functionDemo(input, output, stderr);
* Const parameter
 
* [[Default parameter]]
 
* Open array parameters
 
* Array of const
 
  
== Examples ==
+
{$mode objfpc}
Addition of two [[Integer|integer]]s example:
 
  
<syntaxhighlight>
+
// traditional syntax:
function add(c1, c2 : integer) : integer;
+
// the result is stored in the variable
begin
+
// its name is the same as the function's
add := c1 + c2; //or use result := in Object Pascal/Delphi mode
+
function myLine(const x: real): real;
end;
+
begin
 
+
myLine := 0.5 * x + 2;
var
+
end;
  total: integer;
+
</syntaxhighlight>
 +
If <syntaxhighlight lang="pascal" enclose="none">{$modeswitch result on}</syntaxhighlight>, which is set by [[Mode ObjFPC|<syntaxhighlight lang="pascal" enclose="none">{$mode objFPC}</syntaxhighlight>]] and [[Mode Delphi|<syntaxhighlight lang="pascal" enclose="none">{$mode Delphi}</syntaxhighlight>]], inside the implementation block the special identifier <syntaxhighlight lang="pascal" enclose="none">result</syntaxhighlight> is available, too:
 +
<syntaxhighlight lang="pascal" line start="13">
 +
// using special `result` identifier
 +
function myParabola(const x: real): real;
 +
begin
 +
result := x * x - 1;
 +
end;
 +
</syntaxhighlight>
 +
Additionally, in <syntaxhighlight lang="pascal" enclose="none">{$mode objFPC}</syntaxhighlight>  the routine {{Doc|package=RTL|unit=system|identifier=exit|text=<syntaxhighlight lang="pascal" enclose="none">exit</syntaxhighlight>}} will set the return value, too, ''and'' leave the stack frame.
 +
In the previous two examples further statements could have appeared, and they would have been executed, whilst after an <syntaxhighlight lang="pascal" enclose="none">exit</syntaxhighlight> the routine is ''done''.
 +
This is the behavior a <syntaxhighlight lang="C" enclose="none">return</syntaxhighlight> statement in C or other programming languages has.
 +
<syntaxhighlight lang="pascal" line start="19">
 +
// using exit routine
 +
function even(const x: longint): boolean;
 +
begin
 +
exit(not odd(x));
 +
end;
 +
</syntaxhighlight>
 +
In assembly language other rules apply.
 +
If the return type is an integral value, the accumulator register is used, provided it fits in there:
 +
<syntaxhighlight lang="pascal" line start="25">
 +
// in assembly language:
 +
// return type fits into a single register => use accumulator register
 +
function zero(const x: int64): boolean;
 +
{$ifdef CPUx86_64}
 +
assembler; register;
 +
{$asmMode intel}
 +
asm
 +
// xor modifies flags => put it in front of test
 +
xor rax, rax    // rax := 0 [false]
 +
 +
// examining the assembler output
 +
// we can verify x is stored in register rdi [i.e. not rax]
 +
test x, x        // x = 0 ?
 +
jnz @zero_done  // if x <> 0 then goto done
 +
 +
inc rax          // rax := 1 [true]
 +
@zero_done:
 +
// When you examine the assembler output
 +
// you will notice the compiler automatically inserts code
 +
// that moves the contents of rax to the right spot on the stack.
 +
end;
 +
{$else}
 +
begin
 +
// NOTE: with optimization switches enabled
 +
//      the compiler produces with the following Pascal statement
 +
//      even shorter (and maybe faster) code
 +
//      than the assembler implementation above
 +
result := x = 0;
 +
end;
 +
{$endif}
 +
</syntaxhighlight>
 +
Otherwise, depending on which [[sAsmmode|<syntaxhighlight lang="pascal" enclose="none">{$asmMode}</syntaxhighlight>]] is active, the <syntaxhighlight lang="asm" enclose="none">@result</syntaxhighlight> (Intel) or <syntaxhighlight lang="asm" enclose="none">__result</syntaxhighlight> (AT&T) macro can be used.
 +
<syntaxhighlight lang="pascal" line start="56">
  
begin
+
begin
  total := add(4, 5);
+
end.
  writeln (total); // result is 9
 
end.
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
[[category:Pascal]]
+
Originally Pascal expected ''exact one'' assignment to the result variable (whichever is used).
[[Category:Control Structures]]
+
[[FPC]] however does allow multiple assignments.

Revision as of 23:19, 12 May 2018

Deutsch (de) English (en) español (es) suomi (fi) français (fr) русский (ru)

A function is a routine that, in contrast to procedures, returns a value. A call of a function is virtually substituted by its return value. Depending on the {$extendedSyntax} compiler switch state, non-productive statements involving a function call are allowed or not.

The word function is a reserved word.

return value

In addition to a normal procedure, a function's formal signature contains a return type: The formal parameter list has to be succeeded by a colon and return type. For instance the following function returns a boolean.

function myFunction(const firstParameter: real): boolean;

When implementing functions there are several ways to define the function's return value.

 1program functionDemo(input, output, stderr);
 2
 3{$mode objfpc}
 4
 5// traditional syntax:
 6// the result is stored in the variable
 7// its name is the same as the function's
 8function myLine(const x: real): real;
 9begin
10	myLine := 0.5 * x + 2;
11end;

If {$modeswitch result on}, which is set by {$mode objFPC} and {$mode Delphi}, inside the implementation block the special identifier result is available, too:

13// using special `result` identifier
14function myParabola(const x: real): real;
15begin
16	result := x * x - 1;
17end;

Additionally, in {$mode objFPC} the routine exit will set the return value, too, and leave the stack frame. In the previous two examples further statements could have appeared, and they would have been executed, whilst after an exit the routine is done. This is the behavior a return statement in C or other programming languages has.

19// using exit routine
20function even(const x: longint): boolean;
21begin
22	exit(not odd(x));
23end;

In assembly language other rules apply. If the return type is an integral value, the accumulator register is used, provided it fits in there:

25// in assembly language:
26// return type fits into a single register => use accumulator register
27function zero(const x: int64): boolean;
28{$ifdef CPUx86_64}
29assembler; register;
30{$asmMode intel}
31asm
32	// xor modifies flags => put it in front of test
33	xor rax, rax     // rax := 0 [false]
34	
35	// examining the assembler output
36	// we can verify x is stored in register rdi [i.e. not rax]
37	test x, x        // x = 0 ?
38	jnz @zero_done   // if x <> 0 then goto done
39	
40	inc rax          // rax := 1 [true]
41@zero_done:
42	// When you examine the assembler output
43	// you will notice the compiler automatically inserts code
44	// that moves the contents of rax to the right spot on the stack.
45end;
46{$else}
47begin
48	// NOTE: with optimization switches enabled
49	//       the compiler produces with the following Pascal statement
50	//       even shorter (and maybe faster) code
51	//       than the assembler implementation above
52	result := x = 0;
53end;
54{$endif}

Otherwise, depending on which {$asmMode} is active, the @result (Intel) or __result (AT&T) macro can be used.

56begin
57end.

Originally Pascal expected exact one assignment to the result variable (whichever is used). FPC however does allow multiple assignments.