Sign in Join
Wiki copytemporary

Function: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Function

OldNewLine
1+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. If the [[$extendedSyntax|{$extendedSyntax} compiler switch]] state is off, function calls can not appear as non-productive statements, but have to be or be part of an [[expression]].
2+
3+The word `function` is a [[Reserved word|reserved word]].
4+
5+## Return value
6+
7+In addition to a normal procedure, a function’s formal signature contains a return [[Data type|type]]: The formal parameter list has to be succeeded by a [[Colon|colon]] and return type. For instance the following function returns a [[Boolean]].
8+
9+``` pascal
10+function myFunction(const firstParameter: real): Boolean;
11+```
12+
13+When implementing functions there are several ways to define the function’s return value.
14+
15+``` pascal
16+program functionDemo(input, output, stderr);
17+
18+{$mode objFPC}
19+
20+// traditional syntax:
21+// the result is stored in the variable
22+// its name is the same as the function's
23+function myLine(const x: real): real;
24+begin
25+ myLine := 0.5 * x + 2;
26+end;
27+```
28+
29+If `{$modeswitch result+}`, which is set by [[Mode ObjFPC|{$mode objFPC}]] and [[Mode Delphi|{$mode Delphi}]], inside the implementation block the special [[Identifier|identifier]] `result` is available, too:
30+
31+``` pascal
32+// using special `result` identifier
33+function myParabola(const x: real): real;
34+begin
35+ result := sqr(x) - 1;
36+end;
37+```
38+
39+Additionally, in `{$mode objFPC}` the routine [`exit`](https://www.freepascal.org/docs-html/rtl/system/exit.html) 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.
40+
41+``` pascal
42+// using exit routine
43+function even(const x: longint): Boolean;
44+begin
45+ exit(not odd(x));
46+end;
47+```
48+
49+In [[Assembly language|assembly language]] other rules apply. If the return type is an integral value, the accumulator register is used, provided it fits in there:
50+
51+``` pascal
52+// in assembly language:
53+// return type fits into a single register => use accumulator register
54+function zero(const x: int64): Boolean;
55+{$ifDef CPUx86_64}
56+assembler; register;
57+{$asmMode intel}
58+asm
59+ // xor modifies flags => put it in front of test
60+ xor rax, rax // rax := 0 (remove residue)
61+
62+ test x, x // x = 0 ?
63+ setz al // rax := ZF
64+
65+ // When you examine the assembler output
66+ // you will notice the compiler automatically inserts code
67+ // that moves the contents of rax to the right spot on the stack,
68+ // unless the noStackFrame hint
69+ // (automatically set by some optimization levels)
70+ // instructs the compiler to omit the stack frame if possible.
71+end;
72+{$else}
73+begin
74+ result := x = 0;
75+end;
76+{$endIf}
77+```
78+
79+Otherwise, depending on which [[sAsmmode|{$asmMode}]] is active, the `@result` (Intel) or `__result` (AT&T) macro can be used.
80+
81+``` pascal
82+type
83+ bodyAttributes = record
84+ surfaceArea: real;
85+ volume: real;
86+ end;
87+
88+// in assembly language:
89+// return type doesn't fit into accumulator => @result macro gives address
90+function sphere(const radius: real): bodyAttributes;
91+{$ifDef CPUx86_64}
92+assembler;
93+{$asmMode intel}
94+const
95+ three: longint = 3;
96+ four: longint = 4;
97+var
98+ r: real;
99+asm
100+ pextrq r, radius, 0 // r := (@radius+0)^
101+ lea rax, @result // rax := @result
102+ fld r // radius
103+
104+ fld st(0) // radius radius
105+ fild four // 4 radius radius
106+ fldpi // pi 4 radius radius
107+ fmul // 4*pi radius radius
108+ fxch // radius 4*pi radius
109+ fld st(0) // radius radius 4*pi radius
110+ fmul // radius^2 4*pi radius
111+ fmul // 4*pi*radius^2 radius
112+ fst [rax].bodyAttributes.surfaceArea
113+
114+ fmul // 4*pi*radius^3
115+ fild three // 3 4*pi*radius^3
116+ fdivp // 4/3*pi*radius^3
117+ fst [rax].bodyAttributes.volume
118+end;
119+{$else}
120+begin
121+ sphere.surfaceArea := 4 * pi() * sqr(radius);
122+ sphere.volume := 4 / 3 * pi() * sqr(radius) * abs(radius);
123+end;
124+{$endIf}
125+```
126+
127+Originally Pascal expected *exact one* [[Becomes|assignment]] to the result variable (whichever is used). [[FPC]] however does not prohibit multiple assignments. It will emit a warning if none of the possible result identifiers were used or the exit routine is not written.
128+
129+> Warning
130+> Function result does not seem to be set
131+>
132+> You can get this warning if the [[Compiler|compiler]] thinks that a function return value is not set. This will not be displayed for assembler procedures, or procedures that contain assembler blocks.
133+
134+``` pascal
135+begin
136+ writeLn(sphere(2.0).surfaceArea);
137+end.
138+```
139+
140+Note, in the case of [[Operator overloading|operator overloads]], a special form of a function, a result variable identifier has to be declared in the formal signature. See the article for details.
141+
142+## Remarks
143+
144+[[Pure functions]] are functions that do not depend on an external state.
145+
146+## See also
147+
148+- [[Pascal basics]]
149+- [§ “Using functions and procedures” in the Reference Guide](https://www.freepascal.org/docs-html/ref/refch14.html)
150+- [§ “Intel 80x86 Inline assembler” in the Programmer’s Guide](https://www.freepascal.org/docs-html/prog/progse10.html)
151+
152+---
153+*From the Free Pascal wiki, page "Function", as it stood on 2021-02-20 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history