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

Path: gap4r8 / doc / tut / chap4.txt
Views: 418346
1
2
4 Functions
3
4
You have already seen how to use functions in the GAP library, i.e., how to
5
apply them to arguments.
6
7
In this section you will see how to write functions in the GAP language. You
8
will also see how to use the if statement and declare local variables with
9
the local statement in the function definition. Loop constructions via while
10
and for are discussed further, as are recursive functions.
11
12
13
4.1 Writing Functions
14
15
Writing a function that prints hello, world. on the screen is a simple
16
exercise in GAP.
17
18
 Example 
19
gap> sayhello:= function()
20
> Print("hello, world.\n");
21
> end;
22
function( ) ... end
23

24
25
This function when called will only execute the Print statement in the
26
second line. This will print the string hello, world. on the screen followed
27
by a newline character \n that causes the GAP prompt to appear on the next
28
line rather than immediately following the printed characters.
29
30
The function definition has the following syntax.
31
32
function( arguments ) statements end
33
34
A function definition starts with the keyword function followed by the
35
formal parameter list arguments enclosed in parenthesis ( ). The formal
36
parameter list may be empty as in the example. Several parameters are
37
separated by commas. Note that there must be no semicolon behind the closing
38
parenthesis. The function definition is terminated by the keyword end.
39
40
A GAP function is an expression like an integer, a sum or a list. Therefore
41
it may be assigned to a variable. The terminating semicolon in the example
42
does not belong to the function definition but terminates the assignment of
43
the function to the name sayhello. Unlike in the case of integers, sums, and
44
lists the value of the function sayhello is echoed in the abbreviated
45
fashion function( ) ... end. This shows the most interesting part of a
46
function: its formal parameter list (which is empty in this example). The
47
complete value of sayhello is returned if you use the function Print
48
(Reference: Print).
49
50
 Example 
51
gap> Print(sayhello, "\n");
52
function ( )
53
 Print( "hello, world.\n" );
54
 return;
55
end
56

57
58
Note the additional newline character "\n" in the Print (Reference: Print)
59
statement. It is printed after the object sayhello to start a new line. The
60
extra return statement is inserted by GAP to simplify the process of
61
executing the function.
62
63
The newly defined function sayhello is executed by calling sayhello() with
64
an empty argument list.
65
66
 Example 
67
gap> sayhello();
68
hello, world.
69

70
71
However, this is not a typical example as no value is returned but only a
72
string is printed.
73
74
75
4.2 If Statements
76
77
In the following example we define a function sign which determines the sign
78
of an integer.
79
80
 Example 
81
gap> sign:= function(n)
82
>  if n < 0 then
83
>  return -1;
84
>  elif n = 0 then
85
>  return 0;
86
>  else
87
>  return 1;
88
>  fi;
89
>  end;
90
function( n ) ... end
91
gap> sign(0); sign(-99); sign(11);
92
0
93
-1
94
1
95

96
97
This example also introduces the if statement which is used to execute
98
statements depending on a condition. The if statement has the following
99
syntax.
100
101
if condition then statements elif condition then statements else statements
102
fi
103
104
There may be several elif parts. The elif part as well as the else part of
105
the if statement may be omitted. An if statement is no expression and can
106
therefore not be assigned to a variable. Furthermore an if statement does
107
not return a value.
108
109
Fibonacci numbers are defined recursively by f(1) = f(2) = 1 and f(n) =
110
f(n-1) + f(n-2) for n ≥ 3. Since functions in GAP may call themselves, a
111
function fib that computes Fibonacci numbers can be implemented basically by
112
typing the above equations. (Note however that this is a very inefficient
113
way to compute f(n).)
114
115
 Example 
116
gap> fib:= function(n)
117
>  if n in [1, 2] then
118
>  return 1;
119
>  else
120
>  return fib(n-1) + fib(n-2);
121
>  fi;
122
>  end;
123
function( n ) ... end
124
gap> fib(15);
125
610
126

127
128
There should be additional tests for the argument n being a positive
129
integer. This function fib might lead to strange results if called with
130
other arguments. Try inserting the necessary tests into this example.
131
132
133
4.3 Local Variables
134
135
A function gcd that computes the greatest common divisor of two integers by
136
Euclid's algorithm will need a variable in addition to the formal arguments.
137
138
 Example 
139
gap> gcd:= function(a, b)
140
>  local c;
141
>  while b <> 0 do
142
>  c:= b;
143
>  b:= a mod b;
144
>  a:= c;
145
>  od;
146
>  return c;
147
>  end;
148
function( a, b ) ... end
149
gap> gcd(30, 63);
150
3
151

152
153
The additional variable c is declared as a local variable in the local
154
statement of the function definition. The local statement, if present, must
155
be the first statement of a function definition. When several local
156
variables are declared in only one local statement they are separated by
157
commas.
158
159
The variable c is indeed a local variable, that is local to the function
160
gcd. If you try to use the value of c in the main loop you will see that c
161
has no assigned value unless you have already assigned a value to the
162
variable c in the main loop. In this case the local nature of c in the
163
function gcd prevents the value of the c in the main loop from being
164
overwritten.
165
166
 Example 
167
gap> c:= 7;;
168
gap> gcd(30, 63);
169
3
170
gap> c;
171
7
172

173
174
We say that in a given scope an identifier identifies a unique variable. A
175
scope is a lexical part of a program text. There is the global scope that
176
encloses the entire program text, and there are local scopes that range from
177
the function keyword, denoting the beginning of a function definition, to
178
the corresponding end keyword. A local scope introduces new variables, whose
179
identifiers are given in the formal argument list and the local declaration
180
of the function. The usage of an identifier in a program text refers to the
181
variable in the innermost scope that has this identifier as its name.
182
183
184
4.4 Recursion
185
186
We have already seen recursion in the function fib in Section 4.2. Here is
187
another, slightly more complicated example.
188
189
We will now write a function to determine the number of partitions of a
190
positive integer. A partition of a positive integer is a descending list of
191
numbers whose sum is the given integer. For example [4,2,1,1] is a partition
192
of 8. Note that there is just one partition of 0, namely [ ]. The complete
193
set of all partitions of an integer n may be divided into subsets with
194
respect to the largest element. The number of partitions of n therefore
195
equals the sum of the numbers of partitions of n-i with elements less than
196
or equal to i for all possible i. More generally the number of partitions of
197
n with elements less than m is the sum of the numbers of partitions of n-i
198
with elements less than i for i less than m and n. This description yields
199
the following function.
200
201
 Example 
202
gap> nrparts:= function(n)
203
>  local np;
204
>  np:= function(n, m)
205
>  local i, res;
206
>  if n = 0 then
207
>  return 1;
208
>  fi;
209
>  res:= 0;
210
>  for i in [1..Minimum(n,m)] do
211
>  res:= res + np(n-i, i);
212
>  od;
213
>  return res;
214
>  end;
215
>  return np(n,n);
216
> end;
217
function( n ) ... end
218

219
220
We wanted to write a function that takes one argument. We solved the problem
221
of determining the number of partitions in terms of a recursive procedure
222
with two arguments. So we had to write in fact two functions. The function
223
nrparts that can be used to compute the number of partitions indeed takes
224
only one argument. The function np takes two arguments and solves the
225
problem in the indicated way. The only task of the function nrparts is to
226
call np with two equal arguments.
227
228
We made np local to nrparts. This illustrates the possibility of having
229
local functions in GAP. It is however not necessary to put it there. np
230
could as well be defined on the main level, but then the identifier np would
231
be bound and could not be used for other purposes, and if it were used the
232
essential function np would no longer be available for nrparts.
233
234
Now have a look at the function np. It has two local variables res and i.
235
The variable res is used to collect the sum and i is a loop variable. In the
236
loop the function np calls itself again with other arguments. It would be
237
very disturbing if this call of np was to use the same i and res as the
238
calling np. Since the new call of np creates a new scope with new variables
239
this is fortunately not the case.
240
241
Note that the formal parameters n and m of np are treated like local
242
variables.
243
244
(Regardless of the recursive structure of an algorithm it is often cheaper
245
(in terms of computing time) to avoid a recursive implementation if possible
246
(and it is possible in this case), because a function call is not very
247
cheap.)
248
249
250
4.5 Further Information about Functions
251
252
The function syntax is described in Section 'Reference: Functions'. The if
253
statement is described in more detail in Section 'Reference: If'. More about
254
Fibonacci numbers is found in Section Fibonacci (Reference: Fibonacci) and
255
more about partitions in Section Partitions (Reference: Partitions).
256
257
258