Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
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
Project: cocalc-sagemath-dev-slelievre
Views: 418346<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->1<!-- %% -->2<!-- %W function.tex GAP documentation Thomas Breuer -->3<!-- %W & Frank Celler -->4<!-- %W & Martin Schönert -->5<!-- %W & Heiko Theißen -->6<!-- %% -->7<!-- %H @(#)<M>Id: function.tex,v 4.13 2001/10/06 18:32:31 gap Exp </M> -->8<!-- %% -->9<!-- %Y Copyright 1997, Lehrstuhl D für Mathematik, RWTH Aachen, Germany -->10<!-- %% -->11<!-- %% This file contains a tutorial introduction to functions. -->12<!-- %% -->13<P/>1415<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->16<Chapter Label="Functions">17<Heading>Functions</Heading>1819You have already seen how to use functions in the &GAP; library,20i.e., how to apply them to arguments.21<P/>22In this section you will see how to write functions in the &GAP;23language. You will also see how to use the <K>if</K> statement and declare24local variables with the <K>local</K> statement in the function definition.25Loop constructions via <K>while</K> and <K>for</K> are discussed further, as are26recursive functions.272829<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->30<Section Label="Writing Functions">31<Heading>Writing Functions</Heading>32<P/>33Writing a function that prints <C>hello, world.</C> on the screen is a simple34exercise in &GAP;.35<P/>36<Example><![CDATA[37gap> sayhello:= function()38> Print("hello, world.\n");39> end;40function( ) ... end41]]></Example>42<P/>43This function when called will only execute the <C>Print</C> statement in the44second line. This will print the string <C>hello, world.</C> on the screen45followed by a newline character <C>\n</C> that causes the &GAP; prompt to46appear on the next line rather than immediately following the printed47characters.48<P/>49The function definition has the following syntax.50<P/>51<K>function</K><C>( <A>arguments</A> ) <A>statements</A></C> <K>end</K>52<P/>53A function definition starts with the keyword <K>function</K> followed by54the formal parameter list <A>arguments</A> enclosed in parenthesis55<C>( )</C>.56The formal parameter list may be empty as in the example. Several57parameters are separated by commas. Note that there must be <E>no</E>58semicolon behind the closing parenthesis. The function definition is59terminated by the keyword <K>end</K>.60<P/>61A &GAP; function is an expression like an integer, a sum or a list.62Therefore it may be assigned to a variable. The terminating semicolon63in the example does not belong to the function definition but64terminates the assignment of the function to the name <C>sayhello</C>.65Unlike in the case of integers, sums, and lists the value of the66function <C>sayhello</C> is echoed in the abbreviated fashion67<C>function( ) ... end</C>.68This shows the most interesting part of a function: its69formal parameter list (which is empty in this example). The complete70value of <C>sayhello</C> is returned if you use the function71<Ref Func="Print" BookName="ref"/>.72<P/>73<Example><![CDATA[74gap> Print(sayhello, "\n");75function ( )76Print( "hello, world.\n" );77return;78end79]]></Example>80<P/>81Note the additional newline character <C>"\n"</C> in the82<Ref Func="Print" BookName="ref"/>83statement. It is printed after the object <C>sayhello</C> to start a new84line. The extra <K>return</K> statement is inserted by &GAP; to simplify85the process of executing the function.86<P/>87The newly defined function <C>sayhello</C> is executed by calling <C>sayhello()</C>88with an empty argument list.89<P/>90<Example><![CDATA[91gap> sayhello();92hello, world.93]]></Example>94<P/>95However, this is not a typical example as no value is returned but only a96string is printed.9798</Section>99100101<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->102<Section Label="If Statements">103<Heading>If Statements</Heading>104105In the following example we define a function <C>sign</C> which determines106the sign of an integer.107<P/>108<Example><![CDATA[109gap> sign:= function(n)110> if n < 0 then111> return -1;112> elif n = 0 then113> return 0;114> else115> return 1;116> fi;117> end;118function( n ) ... end119gap> sign(0); sign(-99); sign(11);1200121-11221123]]></Example>124<P/>125This example also introduces the <K>if</K> statement which is used to execute126statements depending on a condition. The <K>if</K> statement has the127following syntax.128<P/>129<K>if</K> <A>condition</A> <K>then</K>130<A>statements</A>131<K>elif</K> <A>condition</A> <K>then</K>132<A>statements</A>133<K>else</K>134<A>statements</A>135<K>fi</K>136<P/>137There may be several <K>elif</K> parts. The <K>elif</K> part as well as the <K>else</K>138part of the <K>if</K> statement may be omitted. An <K>if</K> statement is no139expression and can therefore not be assigned to a variable. Furthermore140an <K>if</K> statement does not return a value.141<P/>142Fibonacci numbers are defined recursively by <M>f(1) = f(2) = 1</M> and143<M>f(n) = f(n-1) + f(n-2)</M> for <M>n \geq 3</M>.144Since functions in &GAP; may call themselves,145a function <C>fib</C> that computes Fibonacci numbers can be implemented146basically by typing the above equations. (Note however that this is a very147inefficient way to compute <M>f(n)</M>.)148<P/>149<Example><![CDATA[150gap> fib:= function(n)151> if n in [1, 2] then152> return 1;153> else154> return fib(n-1) + fib(n-2);155> fi;156> end;157function( n ) ... end158gap> fib(15);159610160]]></Example>161<P/>162There should be additional tests for the argument <C>n</C> being a positive163integer. This function <C>fib</C> might lead to strange results if called164with other arguments. Try inserting the necessary tests into this example.165166</Section>167168169<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->170<Section Label="Local Variables">171<Heading>Local Variables</Heading>172173A function <C>gcd</C> that computes the greatest common divisor of two174integers by Euclid's algorithm will need a variable in addition to the175formal arguments.176<P/>177<Example><![CDATA[178gap> gcd:= function(a, b)179> local c;180> while b <> 0 do181> c:= b;182> b:= a mod b;183> a:= c;184> od;185> return c;186> end;187function( a, b ) ... end188gap> gcd(30, 63);1893190]]></Example>191<P/>192The additional variable <C>c</C> is declared as a <E>local</E> variable in the193<K>local</K> statement of the function definition. The <K>local</K> statement, if194present, must be the first statement of a function definition. When195several local variables are declared in only one <K>local</K> statement they196are separated by commas.197<P/>198The variable <C>c</C> is indeed a local variable, that is local to the199function <C>gcd</C>. If you try to use the value of <C>c</C> in the main loop you200will see that <C>c</C> has no assigned value unless you have already assigned201a value to the variable <C>c</C> in the main loop. In this case the local202nature of <C>c</C> in the function <C>gcd</C> prevents the value of the <C>c</C> in the203main loop from being overwritten.204<P/>205<Example><![CDATA[206gap> c:= 7;;207gap> gcd(30, 63);2083209gap> c;2107211]]></Example>212<P/>213We say that in a given scope an identifier identifies a unique variable.214A <E>scope</E> is a lexical part of a program text. There is the global scope215that encloses the entire program text, and there are local scopes that216range from the <K>function</K> keyword, denoting the beginning of a function217definition, to the corresponding <K>end</K> keyword. A local scope introduces218new variables, whose identifiers are given in the formal argument list219and the local declaration of the function. The usage of an identifier in220a program text refers to the variable in the innermost scope that has221this identifier as its name.222223</Section>224225226<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->227<Section Label="Recursion">228<Heading>Recursion</Heading>229230We have already seen recursion in the function <C>fib</C>231in Section <Ref Sect="If Statements"/>.232Here is another, slightly more complicated example.233<P/>234We will now write a function to determine the number of partitions of235a positive integer. A partition of a positive integer is a descending236list of numbers whose sum is the given integer. For example237<M>[4,2,1,1]</M> is a partition of 8. Note that there is just one partition238of 0, namely <M>[ ]</M>. The complete set of all partitions of an integer239<M>n</M> may be divided into subsets with respect to the largest element.240The number of partitions of <M>n</M> therefore equals the sum of the241numbers of partitions of <M>n-i</M> with elements less than or equal to <M>i</M>242for all possible <M>i</M>. More generally the number of partitions of <M>n</M>243with elements less than <M>m</M> is the sum of the numbers of partitions of244<M>n-i</M> with elements less than <M>i</M> for <M>i</M> less than <M>m</M> and <M>n</M>. This245description yields the following function.246<P/>247<Example><![CDATA[248gap> nrparts:= function(n)249> local np;250> np:= function(n, m)251> local i, res;252> if n = 0 then253> return 1;254> fi;255> res:= 0;256> for i in [1..Minimum(n,m)] do257> res:= res + np(n-i, i);258> od;259> return res;260> end;261> return np(n,n);262> end;263function( n ) ... end264]]></Example>265<P/>266We wanted to write a function that takes one argument. We solved the267problem of determining the number of partitions in terms of a recursive268procedure with two arguments. So we had to write in fact two functions.269The function <C>nrparts</C> that can be used to compute the number of270partitions indeed takes only one argument. The function <C>np</C> takes two271arguments and solves the problem in the indicated way. The only task of272the function <C>nrparts</C> is to call <C>np</C> with two equal arguments.273<P/>274We made <C>np</C> local to <C>nrparts</C>. This illustrates the possibility of275having local functions in &GAP;. It is however not necessary to put276it there. <C>np</C> could as well be defined on the main level, but then277the identifier <C>np</C> would be bound and could not be used for other278purposes, and if it were used the essential function <C>np</C> would no279longer be available for <C>nrparts</C>.280<P/>281Now have a look at the function <C>np</C>. It has two local variables <C>res</C>282and <C>i</C>. The variable <C>res</C> is used to collect the sum and <C>i</C> is a283loop variable. In the loop the function <C>np</C> calls itself again with284other arguments. It would be very disturbing if this call of <C>np</C> was285to use the same <C>i</C> and <C>res</C> as the calling <C>np</C>. Since the new call286of <C>np</C> creates a new scope with new variables this is fortunately not287the case.288<P/>289Note that the formal parameters <A>n</A> and <A>m</A> of <C>np</C> are treated like290local variables.291<P/>292(Regardless of the recursive structure of an algorithm it is often293cheaper (in terms of computing time) to avoid a recursive294implementation if possible (and it is possible in this case), because295a function call is not very cheap.)296297</Section>298299300<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->301<Section Label="Further Information about Functions">302<Heading>Further Information about Functions</Heading>303304The function syntax is described in Section <Ref Chap="Functions" BookName="ref"/>. The <K>if</K>305statement is described in more detail in Section <Ref Sect="If" BookName="ref"/>. More about306Fibonacci numbers is found in Section <Ref Func="Fibonacci" BookName="ref"/> and more about307partitions in Section <Ref Func="Partitions" BookName="ref"/>.308309</Section>310</Chapter>311312313<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->314<!-- %% -->315<!-- %E -->316317318319