Sign in Join
Wiki copytemporary

Function/fi: what changed

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

Title: Function/fi

OldNewLine
1+Funktio eli **function** on [[Routine/fi|rutiini]], joka toisin kuin [[Procedure/fi|aliohjelma (procedure)]] palauttaa arvon. Funktion kutsu käytännössä korvautuu sen palautusarvolla. Jos [[sExtendedsyntax|{$extendedSyntax} kääntäjän kytkin (compiler switch)]] on pois päältä, funktion kutsu ei voi esiintyä ei-tuottavina lauseina, vaan niiden on oltava osa lauseketta.
2+
3+Sana `function` on [[Reserved word/fi|varattu sana]].
4+
5+## Palautusarvo
6+
7+Normaalin aliohjelman esittelyn lisäksi funktion esittely sisältää myös [[Data type/fi|palautustyypin]]: muodollisen parametriluettelon jälkeen tulee [[Colon/fi|kaksoispiste-]] ja palautustyyppi. Seuraava funktion esittely palauttaa esimerkiksi [[Boolean/fi|boolean]] tyyppisen arvon.
8+
9+``` pascal
10+function myFunction(const firstParameter: real): boolean;
11+```
12+
13+Funktion toteuttamisessa on useita tapoja toteuttaa funktion palautusarvo.
14+
15+``` pascal
16+program functionDemo(input, output, stderr);
17+
18+{$mode objfpc}
19+
20+// Perinteinen tapa:
21+// palautus arvo tallennetaan muuttujaan
22+// jonka nimi on sama kuin funktion nimi
23+function myLine(const x: real): real;
24+begin
25+ myLine := 0.5 * x + 2;
26+end;
27+```
28+
29+Jos `{$modeswitch result+}` on käytössä. Se asetetaan [[Mode ObjFPC|{$mode objFPC}]] ja [[Mode Delphi|{$mode Delphi}]], niin toteutuslohkon sisällä on käytössä [[Identifier/fi|tunniste]] `result` myöskin:
30+
31+``` pascal
32+// käytetään `result` tunnistetta
33+function myParabola(const x: real): real;
34+begin
35+ result := sqr(x) - 1;
36+end;
37+```
38+
39+Lisäksi `{$mode objFPC}`:ssa rutiini [`exit`](https://www.freepascal.org/docs-html/rtl/system/exit.html) asettaa myös palautusarvon ja jättää pinoon kehyksen. Kahdessa aikaisemmassa esimerkissä olisi voinut esiintyä muita lausekkeita ja ne olisi toteutettu, kun taas `exit`:n jälkeen palataan funktiosta pois. Tämä on samanlainen käyttäytyminen kuin C:n tai joidenkin muiden ohjelmointikielien `return` lausekkeen käyttäytyminen.
40+
41+``` pascal
42+// käytetään exit rutiinia
43+function even(const x: longint): boolean;
44+begin
45+ exit(not odd(x));
46+end;
47+```
48+
49+[[Assembly language/fi|Assembly kielen]] yhteydessä sovelletaan muita sääntöjä. Jos palautustyyppi on kiinteä arvo, käytetään akku-rekisteriä, jos se mahtuu sinne:
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 [false]
61+
62+ // examining the assembler output
63+ // we can verify x is stored in register rdi [i.e. not rax]
64+ test x, x // x = 0 ?
65+ jnz @zero_done // if x <> 0 then goto done
66+
67+ inc rax // rax := 1 [true]
68+@zero_done:
69+ // When you examine the assembler output
70+ // you will notice the compiler automatically inserts code
71+ // that moves the contents of rax to the right spot on the stack.
72+end;
73+{$else}
74+begin
75+ // NOTE: with optimization switches enabled
76+ // the compiler produces with the following Pascal statement
77+ // even shorter (and maybe faster) code
78+ // than the assembler implementation above
79+ result := x = 0;
80+end;
81+{$endif}
82+```
83+
84+Muuten riippuen siitä, mikä [[sAsmmode|{$asmMode}]] on aktiivinen, `@result` (Intel) tai `__result` (AT&T) -makroa voidaan käyttää.
85+
86+``` pascal
87+type
88+ bodyAttributes = record
89+ surfaceArea: real;
90+ volume: real;
91+ end;
92+
93+// in assembly language:
94+// return type doesn't fit into accumulator => @result macro gives address
95+function sphere(const radius: real): bodyAttributes;
96+{$ifdef CPUx86_64}
97+assembler;
98+{$asmMode intel}
99+const
100+ three: longint = 3;
101+ four: longint = 4;
102+var
103+ r: real;
104+asm
105+ pextrq r, radius, 0 // r := (@radius+0)^
106+ lea rax, @result // rax := @result
107+ fld r // radius
108+
109+ fld st(0) // radius radius
110+ fild four // 4 radius radius
111+ fldpi // pi 4 radius radius
112+ fmul // 4*pi radius radius
113+ fxch // radius 4*pi radius
114+ fld st(0) // radius radius 4*pi radius
115+ fmul // radius^2 4*pi radius
116+ fmul // 4*pi*radius^2 radius
117+ fst [rax].bodyAttributes.surfaceArea
118+
119+ fmul // 4*pi*radius^3
120+ fild three // 3 4*pi*radius^3
121+ fdivp // 4/3*pi*radius^3
122+ fst [rax].bodyAttributes.volume
123+end;
124+{$else}
125+begin
126+ sphere.surfaceArea := 4 * pi() * sqr(radius);
127+ sphere.volume := 4 / 3 * pi() * sqr(radius) * abs(radius);
128+end;
129+{$endif}
130+```
131+
132+Alun perin Pascal odotti täsmällisesti yhden tehtävän tulosmuuttujalle. [[FPC]] ei kuitenkaan kiellä käyttämästä useita. Se lähettää varoituksen, jos mikään mahdollisista palautumisarvoista ei ole käytössä tai poistumisrutiinia ei ole kirjoitettu.
133+
134+> Warning
135+> Function result does not seem to be set
136+>
137+> You can get this warning if the compiler thinks that a function return value is not set. This will not be displayed for assembler procedures, or procedures that contain assembler blocks.
138+
139+``` pascal
140+begin
141+ writeLn(sphere(2.0).surfaceArea);
142+end.
143+```
144+
145+## Katso myös
146+
147+- [§ “Using functions and procedures” in the Reference Guide](https://www.freepascal.org/docs-html/ref/refch14.html)
148+- [§ “Intel 80x86 Inline assembler” in the Programmer's Guide](https://www.freepascal.org/docs-html/prog/progse10.html)
149+
150+---
151+*From the Free Pascal wiki, page "Function/fi", as it stood on 2022-08-06 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