CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

Views: 418346
1
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
2
<!-- %% -->
3
<!-- %W function.tex GAP documentation Thomas Breuer -->
4
<!-- %W & Frank Celler -->
5
<!-- %W & Martin Schönert -->
6
<!-- %W & Heiko Theißen -->
7
<!-- %% -->
8
<!-- %H @(#)<M>Id: function.tex,v 4.13 2001/10/06 18:32:31 gap Exp </M> -->
9
<!-- %% -->
10
<!-- %Y Copyright 1997, Lehrstuhl D für Mathematik, RWTH Aachen, Germany -->
11
<!-- %% -->
12
<!-- %% This file contains a tutorial introduction to functions. -->
13
<!-- %% -->
14
<P/>
15
16
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
17
<Chapter Label="Functions">
18
<Heading>Functions</Heading>
19
20
You have already seen how to use functions in the &GAP; library,
21
i.e., how to apply them to arguments.
22
<P/>
23
In this section you will see how to write functions in the &GAP;
24
language. You will also see how to use the <K>if</K> statement and declare
25
local variables with the <K>local</K> statement in the function definition.
26
Loop constructions via <K>while</K> and <K>for</K> are discussed further, as are
27
recursive functions.
28
29
30
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
31
<Section Label="Writing Functions">
32
<Heading>Writing Functions</Heading>
33
<P/>
34
Writing a function that prints <C>hello, world.</C> on the screen is a simple
35
exercise in &GAP;.
36
<P/>
37
<Example><![CDATA[
38
gap> sayhello:= function()
39
> Print("hello, world.\n");
40
> end;
41
function( ) ... end
42
]]></Example>
43
<P/>
44
This function when called will only execute the <C>Print</C> statement in the
45
second line. This will print the string <C>hello, world.</C> on the screen
46
followed by a newline character <C>\n</C> that causes the &GAP; prompt to
47
appear on the next line rather than immediately following the printed
48
characters.
49
<P/>
50
The function definition has the following syntax.
51
<P/>
52
<K>function</K><C>( <A>arguments</A> ) <A>statements</A></C> <K>end</K>
53
<P/>
54
A function definition starts with the keyword <K>function</K> followed by
55
the formal parameter list <A>arguments</A> enclosed in parenthesis
56
<C>( )</C>.
57
The formal parameter list may be empty as in the example. Several
58
parameters are separated by commas. Note that there must be <E>no</E>
59
semicolon behind the closing parenthesis. The function definition is
60
terminated by the keyword <K>end</K>.
61
<P/>
62
A &GAP; function is an expression like an integer, a sum or a list.
63
Therefore it may be assigned to a variable. The terminating semicolon
64
in the example does not belong to the function definition but
65
terminates the assignment of the function to the name <C>sayhello</C>.
66
Unlike in the case of integers, sums, and lists the value of the
67
function <C>sayhello</C> is echoed in the abbreviated fashion
68
<C>function( ) ... end</C>.
69
This shows the most interesting part of a function: its
70
formal parameter list (which is empty in this example). The complete
71
value of <C>sayhello</C> is returned if you use the function
72
<Ref Func="Print" BookName="ref"/>.
73
<P/>
74
<Example><![CDATA[
75
gap> Print(sayhello, "\n");
76
function ( )
77
Print( "hello, world.\n" );
78
return;
79
end
80
]]></Example>
81
<P/>
82
Note the additional newline character <C>"\n"</C> in the
83
<Ref Func="Print" BookName="ref"/>
84
statement. It is printed after the object <C>sayhello</C> to start a new
85
line. The extra <K>return</K> statement is inserted by &GAP; to simplify
86
the process of executing the function.
87
<P/>
88
The newly defined function <C>sayhello</C> is executed by calling <C>sayhello()</C>
89
with an empty argument list.
90
<P/>
91
<Example><![CDATA[
92
gap> sayhello();
93
hello, world.
94
]]></Example>
95
<P/>
96
However, this is not a typical example as no value is returned but only a
97
string is printed.
98
99
</Section>
100
101
102
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
103
<Section Label="If Statements">
104
<Heading>If Statements</Heading>
105
106
In the following example we define a function <C>sign</C> which determines
107
the sign of an integer.
108
<P/>
109
<Example><![CDATA[
110
gap> sign:= function(n)
111
> if n < 0 then
112
> return -1;
113
> elif n = 0 then
114
> return 0;
115
> else
116
> return 1;
117
> fi;
118
> end;
119
function( n ) ... end
120
gap> sign(0); sign(-99); sign(11);
121
0
122
-1
123
1
124
]]></Example>
125
<P/>
126
This example also introduces the <K>if</K> statement which is used to execute
127
statements depending on a condition. The <K>if</K> statement has the
128
following syntax.
129
<P/>
130
<K>if</K> <A>condition</A> <K>then</K>
131
<A>statements</A>
132
<K>elif</K> <A>condition</A> <K>then</K>
133
<A>statements</A>
134
<K>else</K>
135
<A>statements</A>
136
<K>fi</K>
137
<P/>
138
There may be several <K>elif</K> parts. The <K>elif</K> part as well as the <K>else</K>
139
part of the <K>if</K> statement may be omitted. An <K>if</K> statement is no
140
expression and can therefore not be assigned to a variable. Furthermore
141
an <K>if</K> statement does not return a value.
142
<P/>
143
Fibonacci numbers are defined recursively by <M>f(1) = f(2) = 1</M> and
144
<M>f(n) = f(n-1) + f(n-2)</M> for <M>n \geq 3</M>.
145
Since functions in &GAP; may call themselves,
146
a function <C>fib</C> that computes Fibonacci numbers can be implemented
147
basically by typing the above equations. (Note however that this is a very
148
inefficient way to compute <M>f(n)</M>.)
149
<P/>
150
<Example><![CDATA[
151
gap> fib:= function(n)
152
> if n in [1, 2] then
153
> return 1;
154
> else
155
> return fib(n-1) + fib(n-2);
156
> fi;
157
> end;
158
function( n ) ... end
159
gap> fib(15);
160
610
161
]]></Example>
162
<P/>
163
There should be additional tests for the argument <C>n</C> being a positive
164
integer. This function <C>fib</C> might lead to strange results if called
165
with other arguments. Try inserting the necessary tests into this example.
166
167
</Section>
168
169
170
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
171
<Section Label="Local Variables">
172
<Heading>Local Variables</Heading>
173
174
A function <C>gcd</C> that computes the greatest common divisor of two
175
integers by Euclid's algorithm will need a variable in addition to the
176
formal arguments.
177
<P/>
178
<Example><![CDATA[
179
gap> gcd:= function(a, b)
180
> local c;
181
> while b <> 0 do
182
> c:= b;
183
> b:= a mod b;
184
> a:= c;
185
> od;
186
> return c;
187
> end;
188
function( a, b ) ... end
189
gap> gcd(30, 63);
190
3
191
]]></Example>
192
<P/>
193
The additional variable <C>c</C> is declared as a <E>local</E> variable in the
194
<K>local</K> statement of the function definition. The <K>local</K> statement, if
195
present, must be the first statement of a function definition. When
196
several local variables are declared in only one <K>local</K> statement they
197
are separated by commas.
198
<P/>
199
The variable <C>c</C> is indeed a local variable, that is local to the
200
function <C>gcd</C>. If you try to use the value of <C>c</C> in the main loop you
201
will see that <C>c</C> has no assigned value unless you have already assigned
202
a value to the variable <C>c</C> in the main loop. In this case the local
203
nature of <C>c</C> in the function <C>gcd</C> prevents the value of the <C>c</C> in the
204
main loop from being overwritten.
205
<P/>
206
<Example><![CDATA[
207
gap> c:= 7;;
208
gap> gcd(30, 63);
209
3
210
gap> c;
211
7
212
]]></Example>
213
<P/>
214
We say that in a given scope an identifier identifies a unique variable.
215
A <E>scope</E> is a lexical part of a program text. There is the global scope
216
that encloses the entire program text, and there are local scopes that
217
range from the <K>function</K> keyword, denoting the beginning of a function
218
definition, to the corresponding <K>end</K> keyword. A local scope introduces
219
new variables, whose identifiers are given in the formal argument list
220
and the local declaration of the function. The usage of an identifier in
221
a program text refers to the variable in the innermost scope that has
222
this identifier as its name.
223
224
</Section>
225
226
227
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
228
<Section Label="Recursion">
229
<Heading>Recursion</Heading>
230
231
We have already seen recursion in the function <C>fib</C>
232
in Section&nbsp;<Ref Sect="If Statements"/>.
233
Here is another, slightly more complicated example.
234
<P/>
235
We will now write a function to determine the number of partitions of
236
a positive integer. A partition of a positive integer is a descending
237
list of numbers whose sum is the given integer. For example
238
<M>[4,2,1,1]</M> is a partition of 8. Note that there is just one partition
239
of 0, namely <M>[ ]</M>. The complete set of all partitions of an integer
240
<M>n</M> may be divided into subsets with respect to the largest element.
241
The number of partitions of <M>n</M> therefore equals the sum of the
242
numbers of partitions of <M>n-i</M> with elements less than or equal to <M>i</M>
243
for all possible <M>i</M>. More generally the number of partitions of <M>n</M>
244
with elements less than <M>m</M> is the sum of the numbers of partitions of
245
<M>n-i</M> with elements less than <M>i</M> for <M>i</M> less than <M>m</M> and <M>n</M>. This
246
description yields the following function.
247
<P/>
248
<Example><![CDATA[
249
gap> nrparts:= function(n)
250
> local np;
251
> np:= function(n, m)
252
> local i, res;
253
> if n = 0 then
254
> return 1;
255
> fi;
256
> res:= 0;
257
> for i in [1..Minimum(n,m)] do
258
> res:= res + np(n-i, i);
259
> od;
260
> return res;
261
> end;
262
> return np(n,n);
263
> end;
264
function( n ) ... end
265
]]></Example>
266
<P/>
267
We wanted to write a function that takes one argument. We solved the
268
problem of determining the number of partitions in terms of a recursive
269
procedure with two arguments. So we had to write in fact two functions.
270
The function <C>nrparts</C> that can be used to compute the number of
271
partitions indeed takes only one argument. The function <C>np</C> takes two
272
arguments and solves the problem in the indicated way. The only task of
273
the function <C>nrparts</C> is to call <C>np</C> with two equal arguments.
274
<P/>
275
We made <C>np</C> local to <C>nrparts</C>. This illustrates the possibility of
276
having local functions in &GAP;. It is however not necessary to put
277
it there. <C>np</C> could as well be defined on the main level, but then
278
the identifier <C>np</C> would be bound and could not be used for other
279
purposes, and if it were used the essential function <C>np</C> would no
280
longer be available for <C>nrparts</C>.
281
<P/>
282
Now have a look at the function <C>np</C>. It has two local variables <C>res</C>
283
and <C>i</C>. The variable <C>res</C> is used to collect the sum and <C>i</C> is a
284
loop variable. In the loop the function <C>np</C> calls itself again with
285
other arguments. It would be very disturbing if this call of <C>np</C> was
286
to use the same <C>i</C> and <C>res</C> as the calling <C>np</C>. Since the new call
287
of <C>np</C> creates a new scope with new variables this is fortunately not
288
the case.
289
<P/>
290
Note that the formal parameters <A>n</A> and <A>m</A> of <C>np</C> are treated like
291
local variables.
292
<P/>
293
(Regardless of the recursive structure of an algorithm it is often
294
cheaper (in terms of computing time) to avoid a recursive
295
implementation if possible (and it is possible in this case), because
296
a function call is not very cheap.)
297
298
</Section>
299
300
301
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
302
<Section Label="Further Information about Functions">
303
<Heading>Further Information about Functions</Heading>
304
305
The function syntax is described in Section <Ref Chap="Functions" BookName="ref"/>. The <K>if</K>
306
statement is described in more detail in Section <Ref Sect="If" BookName="ref"/>. More about
307
Fibonacci numbers is found in Section <Ref Func="Fibonacci" BookName="ref"/> and more about
308
partitions in Section <Ref Func="Partitions" BookName="ref"/>.
309
310
</Section>
311
</Chapter>
312
313
314
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
315
<!-- %% -->
316
<!-- %E -->
317
318
319