-
Notifications
You must be signed in to change notification settings - Fork 181
Expand file tree
/
Copy pathlanguage.xml
More file actions
2408 lines (2242 loc) · 82.9 KB
/
language.xml
File metadata and controls
2408 lines (2242 loc) · 82.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<!-- %% -->
<!-- %W language.xml GAP documentation Martin Schönert -->
<!-- %% -->
<!-- %% -->
<!-- %Y Copyright 1990-1992, Lehrstuhl D für Mathematik, RWTH Aachen, Germany -->
<!-- %% -->
<!-- %% This file describes the &GAP; programming language. -->
<!-- %% -->
<Chapter Label="The Programming Language">
<Heading>The Programming Language</Heading>
This chapter describes the &GAP; programming language. It should allow
you, in principle, to predict the result of each and every input. In order
to know what we are talking about, we first have to look more closely at
the process of interpretation and the various representations of data
involved.
<!-- %% The &GAP; language and its interpreter in the kernel were designed by -->
<!-- %% Martin Sch{\"o}nert. -->
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Language Overview">
<Heading>Language Overview</Heading>
First we have the input to &GAP;, given as a string of characters. How
those characters enter &GAP; is operating system dependent, e.g., they
might be entered at a terminal, pasted with a mouse into a window, or
read from a file. The mechanism does not matter. This representation of
expressions by characters is called the <E>external representation</E> of the
expression. Every expression has at least one external representation
that can be entered to get exactly this expression.
<P/>
The input, i.e., the external representation, is transformed in a process
called <E>reading</E> to an internal representation. At this point the input
is analyzed and inputs that are not legal external representations,
according to the rules given below, are rejected as errors. Those rules
are usually called the <E>syntax</E> of a programming language.
<P/>
The internal representation created by reading is called either an
<E>expression</E> or a <E>statement</E>.
Later we will distinguish between those two terms.
However for now we will use them interchangeably.
The exact form of the internal representation does not matter.
It could be a string of characters equal to the external representation,
in which case the reading would only need to check for errors.
It could be a series of machine instructions for the processor on which
&GAP; is running, in which case the reading would more appropriately
be called compilation.
It is in fact a tree-like structure.
<P/>
After the input has been read it is again transformed in a process called
<E>evaluation</E> or <E>execution</E>.
Later we will distinguish between those two terms too,
but for the moment we will use them interchangeably. The name
hints at the nature of this process, it replaces an expression with the
value of the expression. This works recursively, i.e., to evaluate an
expression first the subexpressions are evaluated and then the value of
the expression is computed from those values according to rules given below.
Those rules are usually called the <E>semantics</E> of a programming language.
<P/>
The result of the evaluation is, not surprisingly, called a <E>value</E>.
<!-- % The -->
<!-- % set of values is of course a much smaller set than the set of -->
<!-- % expressions; for every value there may be several expressions that will -->
<!-- % evaluate to this value. -->
Again the form in which such a value is
represented internally does not matter. It is in fact a tree-like
structure again.
<P/>
The last process is called <E>printing</E>. It takes the value produced by
the evaluation and creates an external representation, i.e., a string of
characters again. What you do with this external representation is up to
you. You can look at it, paste it with the mouse into another window, or
write it to a file.
<P/>
Lets look at an example to make this more clear. Suppose you type in the
following string of 8 characters
<P/>
<Listing><![CDATA[
1 + 2 * 3;
]]></Listing>
<P/>
&GAP; takes this external representation and creates a tree-like
internal representation, which we can picture as follows
<P/>
<Listing><![CDATA[
+
/ \
1 *
/ \
2 3
]]></Listing>
<P/>
This expression is then evaluated. To do this &GAP; first evaluates the
right subexpression <C>2*3</C>. Again, to do this &GAP; first evaluates its
subexpressions 2 and 3. However they are so simple that they are their
own value, we say that they are self-evaluating. After this has been
done, the rule for <C>*</C> tells us that the value is the product of the
values of the two subexpressions, which in this case is clearly 6.
Combining this with the value of the left operand of the <C>+</C>, which is
self-evaluating, too, gives us the value of the whole expression 7. This
is then printed, i.e., converted into the external representation
consisting of the single character <C>7</C>.
<P/>
In this fashion we can predict the result of every input when we know the
syntactic rules that govern the process of reading and the semantic rules
that tell us for every expression how its value is computed in terms of
the values of the subexpressions.
The syntactic rules are given in sections <Ref Sect="Lexical Structure"/>,
<Ref Sect="Symbols"/>, <Ref Sect="Whitespaces"/>, <Ref Sect="Keywords"/>,
and <Ref Sect="Identifiers"/>,
the semantic rules are given in sections <Ref Sect="Expressions"/>,
<Ref Sect="Variables"/>, <Ref Sect="Function Calls"/>,
<Ref Sect="Comparisons"/>, <Ref Sect="Arithmetic Operators"/>,
<Ref Sect="Statements"/>, <Ref Sect="Assignments"/>,
<Ref Sect="Procedure Calls"/>, <Ref Sect="If"/>, <Ref Sect="While"/>,
<Ref Sect="Repeat"/>, <Ref Sect="For"/>, <Ref Sect="Function"/>,
and the chapters describing the individual data types.
</Section>
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Lexical Structure">
<Heading>Lexical Structure</Heading>
Most input of &GAP; consists of sequences of the following characters.
<P/>
Digits, uppercase and lowercase letters, <B>Space</B>, <B>Tab</B>,
<B>Newline</B>, <B>Return</B> and the special characters
<P/>
<Listing><![CDATA[
" ' ( ) * + , - #
. / : ; < = > ~
[ \ ] ^ _ { } !
]]></Listing>
<P/>
It is possible to use other characters in identifiers by escaping
them with backslashes, but we do not recommend the use of this feature.
Inside strings
(see section <Ref Sect="Symbols"/> and
chapter <Ref Chap="Strings and Characters"/>)
and comments (see <Ref Sect="Whitespaces"/>) the full character set
supported by the computer is allowed.
</Section>
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Symbols">
<Heading>Symbols</Heading>
The process of reading, i.e., of assembling the input into expressions,
has a subprocess, called <E>scanning</E>, that assembles the characters into
symbols. A <E>symbol</E> is a sequence of characters that form a lexical
unit. The set of symbols consists of keywords, identifiers, strings,
integers, and operator and delimiter symbols.
<P/>
A <E>keyword</E> is a reserved word (see <Ref Sect="Keywords"/>).
An <E>identifier</E> is a sequence of letters, digits and underscores
(or other characters escaped by backslashes) that contains at least one
non-digit and is not a keyword (see <Ref Sect="Identifiers"/>).
An integer is a sequence of digits (see <Ref Chap="Integers"/>),
possibly prepended by <C>-</C> and <C>+</C> sign characters.
A <E>string</E> is a sequence of arbitrary characters enclosed in
double quotes (see <Ref Chap="Strings and Characters"/>).
<P/>
Operator and delimiter symbols are
<P/>
<Listing><![CDATA[
+ - * / ^ ~ !.
= <> < <= > >= ![
:= . .. -> , ; [
] { } ( ) :
]]></Listing>
<P/>
Note also that during the process of scanning all whitespace is removed
(see <Ref Sect="Whitespaces"/>).
</Section>
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Whitespaces">
<Heading>Whitespaces</Heading>
<Index>space</Index>
<Index>blank</Index><Index>tabulator</Index><Index>newline</Index>
<Index>comments</Index><Index>#</Index>
The characters <B>Space</B>, <B>Tab</B>, <B>Newline</B>, and <B>Return</B>
are called <E>whitespace characters</E>.
Whitespace is used as necessary to separate lexical symbols,
such as integers, identifiers, or keywords. For example
<C>Thorondor</C> is a single identifier,
while <C>Th or ondor</C> is the keyword <K>or</K> between the two identifiers
<C>Th</C> and <C>ondor</C>.
Whitespace may occur between any two symbols, but not within a symbol.
Two or more adjacent whitespace characters are equivalent to a single
whitespace.
Apart from the role as separator of symbols,
whitespace characters are otherwise insignificant.
Whitespace characters may also occur inside a string,
where they are significant.
Whitespace characters should also be used freely for improved readability.
<P/>
A <E>comment</E> starts with the character <C>#</C>,
which is sometimes called sharp or hatch,
and continues to the end of the line on which the comment character appears.
The whole comment, including <C>#</C> and the <B>Newline</B> character
is treated as a single whitespace.
Inside a string, the comment character <C>#</C> loses its role and is just
an ordinary character.
<P/>
For example, the following statement
<P/>
<Listing><![CDATA[
if i<0 then a:=-i;else a:=i;fi;
]]></Listing>
<P/>
is equivalent to
<P/>
<Listing><![CDATA[
if i < 0 then # if i is negative
a := -i; # take its additive inverse
else # otherwise
a := i; # take itself
fi;
]]></Listing>
<P/>
(which by the way shows that it is possible to write superfluous
comments). However the first statement is <E>not</E> equivalent to
<P/>
<Listing><![CDATA[
ifi<0thena:=-i;elsea:=i;fi;
]]></Listing>
<P/>
since the keyword <K>if</K> must be separated from the identifier <C>i</C>
by a whitespace, and similarly <K>then</K> and <C>a</C>,
and <K>else</K> and <C>a</C> must be separated.
</Section>
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Keywords">
<Heading>Keywords</Heading>
<Index Key="GAPInfo.Keywords"><C>GAPInfo.Keywords</C></Index>
<E>Keywords</E> are reserved words that are used to denote special operations
or are part of statements. They must not be used as identifiers. The list of
keywords is contained in the <C>GAPInfo.Keywords</C> component of the
<C>GAPInfo</C> record (see <Ref Sect="GAPInfo"/>). We will show how to print
it in a nice table, demonstrating at the same time some list manipulation
techniques:
<P/>
<Example><![CDATA[
gap> keys:=SortedList( GAPInfo.Keywords );; l:=Length( keys );;
gap> arr:= List( [ 0 .. Int( l/4 )-1 ], i-> keys{ 4*i + [ 1 .. 4 ] } );;
gap> if l mod 4 <> 0 then Add( arr, keys{[ 4*Int(l/4) + 1 .. l ]} ); fi;
gap> Length( keys ); PrintArray( arr );
35
[ [ Assert, Info, IsBound, QUIT ],
[ TryNextMethod, Unbind, and, atomic ],
[ break, continue, do, elif ],
[ else, end, false, fi ],
[ for, function, if, in ],
[ local, mod, not, od ],
[ or, quit, readonly, readwrite ],
[ rec, repeat, return, then ],
[ true, until, while ] ]
]]></Example>
<P/>
Note that (almost) all keywords are written in lowercase and that they
are case sensitive.
For example <K>else</K> is a keyword; <C>Else</C>, <C>eLsE</C>, <C>ELSE</C>
and so forth are ordinary identifiers.
Keywords must not contain whitespace, for example <C>el if</C> is not the
same as <K>elif</K>.
<P/>
<E>Note</E>:
Several tokens from the list of keywords above may appear to be normal
identifiers representing functions or literals of various kinds but are
actually implemented as keywords for technical reasons. The only
consequence of this is that those identifiers cannot be re-assigned, and
do not actually have function objects bound to them, which could be
assigned to other variables or passed to functions. These keywords are
<K>true</K>, <K>false</K>, <Ref Func="Assert"/>,
<Ref Func="IsBound" Label="for a global variable"/>,
<Ref Func="Unbind" Label="unbind a variable"/>,
<Ref Func="Info"/> and <Ref Func="TryNextMethod"/>.
<P/>
<!-- Update the next paragraph to reference HPC-GAP suitably -->
Keywords <C>atomic</C>, <C>readonly</C>, <C>readwrite</C> are not used
at the moment. They are reserved for the future version of GAP to prevent
their accidental use as identifiers.
</Section>
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Identifiers">
<Heading>Identifiers</Heading>
An <E>identifier</E> is used to refer to a variable
(see <Ref Sect="Variables"/>).
An identifier usually consists of letters, digits, underscores <C>_</C>,
and <Q>at</Q>-characters <C>@</C>,
and must contain at least one non-digit.
An identifier is terminated by the first character not in this class.
Note that the <Q>at</Q>-character <C>@</C> is used to implement
namespaces, see Section <Ref Sect="Namespaces"/> for details.
<P/>
Examples of valid identifiers are
<P/>
<Listing><![CDATA[
a foo aLongIdentifier
hello Hello HELLO
x100 100x _100
some_people_prefer_underscores_to_separate_words
WePreferMixedCaseToSeparateWords
abc@def
]]></Listing>
<P/>
Note that case is significant, so the three identifiers in the second
line are distinguished.
<P/>
The backslash <C>\</C> can be used to include other characters in identifiers;
a backslash followed by a character is equivalent to the character,
except that this escape sequence is considered to be an ordinary letter.
For example
<Listing><![CDATA[
G\(2\,5\)
]]></Listing>
is an identifier, not a call to a function <C>G</C>.
<P/>
An identifier that starts with a backslash is never a keyword, so for
example <C>\*</C> and <C>\mod</C> are identifiers.
<P/>
The length of identifiers is not limited,
however only the first <M>1023</M> characters are significant.
The escape sequence <C>\</C><B>newline</B> is ignored,
making it possible to split long identifiers over multiple lines.
<#Include Label="IsValidIdentifier">
Note that the <Q>at</Q>-character is used to implement namespaces
for global variables in packages. See <Ref Sect="Namespaces"/> for
details.
<Index>namespace</Index>
<Subsection Label="Conventions about Identifiers">
<Heading>Conventions about Identifiers</Heading>
<Index>variable names</Index>
(The following rule is stated also in Section
<Ref Sect="Variables versus Objects" BookName="tut"/>.)
<P/>
The name of almost every global variable in the &GAP; library
and in &GAP; packages starts with a <E>capital letter</E>.
(See Section <Ref Sect="Main Loop"/> for the few exceptions.)
For user variables, we recommend only choosing names that start with a
<E>lower case letter</E>, in order to avoid name clashes.
<P/>
For example, valid &GAP; input which assigns some user variables whose names
start with capital letters may run into errors with a newer version of &GAP;
or in a &GAP; session with more or newer packages,
because it may happen that these variables are predefined global variables
in this situation.
</Subsection>
</Section>
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Expressions">
<Heading>Expressions</Heading>
<Index>evaluation</Index>
An <E>expression</E> is a construct that evaluates to a value.
Syntactic constructs that are executed to produce a side effect and return
no value are called <E>statements</E> (see <Ref Sect="Statements"/>).
Expressions appear as right hand sides of assignments
(see <Ref Sect="Assignments"/>), as actual arguments in function calls
(see <Ref Sect="Function Calls"/>), and in statements.
<P/>
Note that an expression is not the same as a value.
For example <C>1 + 11</C> is an expression, whose value is the integer 12.
The external representation of this integer is the character sequence
<C>12</C>, i.e., this sequence is output if the integer is printed.
This sequence is another expression whose value is the integer <M>12</M>.
The process of finding the value of an expression is done by the interpreter
and is called the <E>evaluation</E> of the expression.
<P/>
The simplest cases of expressions are the following:
<List>
<Item>variables (see Section <Ref Sect="Variables"/>),</Item>
<Item>function literals (see Section <Ref Sect="Function"/>),</Item>
<Item>function calls (see Section <Ref Sect="Function Calls"/>),</Item>
<Item>integer literals (see Chapter <Ref Chap="Integers"/>),</Item>
<Item>floating point literals (see Chapter <Ref Chap="Floats"/>),</Item>
<Item>permutation literals (see Chapter <Ref Chap="Permutations"/>),</Item>
<Item>string literals (see Chapter <Ref Chap="Strings and Characters"/>),</Item>
<Item>character literals (see Chapter <Ref Chap="Strings and Characters"/>),</Item>
<Item>list literals (see Chapter <Ref Chap="Lists"/>), and</Item>
<Item>record literals (see Chapter <Ref Chap="Records"/>).</Item>
</List>
Expressions, for example the simple expressions mentioned above, can be
combined with the operators to form more complex expressions. Of course
those expressions can then be combined further with the operators to form
even more complex expressions. The <E>operators</E> fall into three classes.
<Index>operators</Index>
The <E>comparisons</E> are <C>=</C>, <C><></C>, <C><</C>, <C><=</C>,
<C>></C>, <C>>=</C>, and <K>in</K> (see <Ref Sect="Comparisons"/> and
<Ref Sect="Membership Test for Collections"/>).
The <E>arithmetic operators</E> are <C>+</C>, <C>-</C>, <C>*</C>, <C>/</C>,
<K>mod</K>, and <C>^</C> (see <Ref Sect="Arithmetic Operators"/>).
The <E>logical operators</E> are <K>not</K>, <K>and</K>, and <K>or</K>
(see <Ref Sect="Operations for Booleans"/>).
<P/>
The following example shows a very simple expression with value 4 and a
more complex expression.
<P/>
<Example><![CDATA[
gap> 2 * 2;
4
gap> 2 * 2 + 9 = Fibonacci(7) and Fibonacci(13) in Primes;
true
]]></Example>
<P/>
The following table lists all operators by precedence, from highest to
lowest, and also indicates whether the operator is left associative (aka
left-to-right) or right associative (aka right-to-left) or neither.
<Index>precedence</Index>
<Index>associativity</Index>
<Table Align="ll">
<Row>
<Item><E>operator</E></Item>
<Item><E>associativity</E></Item>
</Row>
<HorLine/>
<Row>
<Item><E>arithmetic (see <Ref Sect="Arithmetic Operators"/>)</E></Item>
<Item></Item>
</Row>
<Row>
<Item> <C>^</C></Item>
<Item>none</Item>
</Row>
<Row>
<Item> unary <C>+</C>, unary <C>-</C></Item>
<Item>right-to-left</Item>
</Row>
<Row>
<Item> <C>*</C>, <C>/</C>, <K>mod</K></Item>
<Item>left-to-right</Item>
</Row>
<Row>
<Item> binary <C>+</C>, binary <C>-</C></Item>
<Item>left-to-right</Item>
</Row>
<HorLine/>
<Row>
<Item><E>comparison (see <Ref Sect="Comparisons"/>)</E></Item>
<Item></Item>
</Row>
<Row>
<Item> <C>=</C>, <C><></C>, <C><</C>, <C><=</C>, <C>></C>, <C>>=</C>, and <K>in</K></Item>
<Item>none</Item>
</Row>
<HorLine/>
<Row>
<Item><E>logical (see <Ref Sect="Operations for Booleans"/>)</E></Item>
<Item></Item>
</Row>
<Row>
<Item> <K>not</K></Item>
<Item>right-to-left</Item>
</Row>
<Row>
<Item> <K>and</K></Item>
<Item>left-to-right</Item>
</Row>
<Row>
<Item> <K>or</K></Item>
<Item>left-to-right</Item>
</Row>
</Table>
</Section>
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Variables">
<Heading>Variables</Heading>
<Index>scope</Index><Index>bound</Index>
A <E>variable</E> is a location in a &GAP; program that points to a value.
We say the variable is <E>bound</E> to this value.
If a variable is evaluated it evaluates to this value.
<P/>
Initially an ordinary variable is not bound to any value.
The variable can be bound to a value by <E>assigning</E> this value to the
variable (see <Ref Sect="Assignments"/>).
Because of this we sometimes say that a variable that is not bound to any
value has no assigned value.
Assignment is in fact the only way by which a variable, which is not an
argument of a function, can be bound to a value.
After a variable has been bound to a value an assignment can also be used
to bind the variable to another value.
<P/>
A special class of variables is the class of <E>arguments</E> of functions.
They behave similarly to other variables,
except they are bound to the value of the
actual arguments upon a function call (see <Ref Sect="Function Calls"/>).
<P/>
Each variable has a name that is also called its <E>identifier</E>. This is
because in a given scope an identifier identifies a unique variable (see
<Ref Sect="Identifiers"/>).
A <E>scope</E> is a lexical part of a program text. There is
the <E>global scope</E> that encloses the entire program text, and there are
local scopes that range from the <K>function</K> keyword, denoting the
beginning of a function definition, to the corresponding <K>end</K> keyword.
A <E>local scope</E> introduces new variables, whose identifiers are given in
the formal argument list and the <K>local</K> declaration of the function (see
<Ref Sect="Function"/>). Usage of an identifier in a program text refers to the
variable in the innermost scope that has this identifier as its name.
Because this mapping from identifiers to variables is done when the
program is read, not when it is executed, &GAP; is said to have <E>lexical
scoping</E>. The following example shows how one identifier refers to
different variables at different points in the program text.
<P/>
<Listing><![CDATA[
g := 0; # global variable g
x := function ( a, b, c )
local y;
g := c; # c refers to argument c of function x
y := function ( y )
local d, e, f;
d := y; # y refers to argument y of function y
e := b; # b refers to argument b of function x
f := g; # g refers to global variable g
return d + e + f;
end;
return y( a ); # y refers to local y of function x
end;
]]></Listing>
<P/>
It is important to note that the concept of a variable in &GAP; is quite
different from the concept of a variable in most compiled programming languages.
<P/>
In those languages a variable denotes a block of memory. The
value of the variable is stored in this block. So in those languages two
variables can have the same value, but they can never have identical
values, because they denote different blocks of memory. Note that
some languages have the concept of a reference argument. It seems as if such an
argument and the variable used in the actual function call have the same
value, since changing the argument's value also changes the value of the
variable used in the actual function call. But this is not so; the
reference argument is actually a pointer to the variable used in the
actual function call, and it is the compiler that inserts enough magic to
make the pointer invisible. In order for this to work the compiler
needs enough information to compute the amount of memory needed for each
variable in a program, which is readily available in the declarations.
<P/>
In &GAP; on the other hand each variable just points to a value,
and different variables can share the same value.
<ManSection>
<Func Name="IsBound" Arg='ident' Label="for a global variable"/>
<Description>
<Ref Func="IsBound" Label="for a global variable"/> returns <K>true</K>
if the variable <A>ident</A> points to a value,
and <K>false</K> otherwise.
<P/>
For records and lists <Ref Func="IsBound" Label="for a global variable"/>
can be used to check whether components or entries, respectively,
are bound
(see Chapters <Ref Chap="Records"/> and <Ref Chap="Lists"/>).
</Description>
</ManSection>
<ManSection>
<Func Name="Unbind" Arg='ident' Label="unbind a variable"/>
<Description>
deletes the identifier <A>ident</A>.
If there is no other variable pointing to the same value as <A>ident</A> was,
this value will be removed by the next garbage collection.
Therefore <Ref Func="Unbind" Label="unbind a variable"/> can be used to get
rid of unwanted large objects.
<P/>
For records and lists <Ref Func="Unbind" Label="unbind a variable"/>
can be used to delete components or entries, respectively
(see Chapters <Ref Chap="Records"/> and <Ref Chap="Lists"/>).
</Description>
</ManSection>
</Section>
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="More About Global Variables">
<Heading>More About Global Variables</Heading>
The vast majority of variables in &GAP; are defined at the outer
level (the global scope). They are used to access functions and
other objects created either in the &GAP; library or packages or in the user's
code.
<P/>
Note that for packages there is a mechanism to implement package local
namespaces on top of this global namespace. See Section <Ref
Sect="Namespaces"/> for details.
<Index>namespace</Index>
<P/>
Certain special facilities are provided for manipulating global
variables which are not available for other types of variable (such as
local variables or function arguments).
<P/>
First, such variables may be marked <E>read-only</E> using
<Ref Func="MakeReadOnlyGlobal"/>. In which case
attempts to change them will fail. Most of the global variables
defined in the &GAP; library are so marked. <E>read-only</E> variables
can be made read-write again by calling <Ref Func="MakeReadWriteGlobal"/>.
GAP also features <E>constant</E> variables, which are created by calling
<Ref Func="MakeConstantGlobal"/>. Constant variables can never be changed.
In some cases, GAP can optimise code which uses <E>constant</E> variables,
as their value never changes. In this version GAP these optimisations can be
observed by printing the function back out, but this behaviour may change
in future.
<Example><![CDATA[
gap> globali := 1 + 2;;
gap> globalb := true;;
gap> MakeConstantGlobal("globali");
gap> MakeConstantGlobal("globalb");
gap> f := function()
> if globalb then
> return globali + 1;
> else
> return globali + 2;
> fi;
> end;;
gap> Print(f);
function ( )
return 3 + 1;
end
]]></Example>
<P/>
Second, a group of functions are supplied for accessing and altering the
values assigned to global variables. Use of these functions differs
from the use of assignment,
<Ref Func="Unbind" Label="unbind a variable"/> and
<Ref Func="IsBound" Label="for a global variable"/>
statements, in two ways.
First, these functions always affect global variables, even if
local variables of the same names exist.
Second, the variable names are passed as strings,
rather than being written directly into the statements.
<P/>
Note that the functions <Ref Func="NamesGVars"/>,
<Ref Func="NamesSystemGVars"/>, and <Ref Func="NamesUserGVars"/>,
deal with the <E>global namespace</E>.
<ManSection>
<Func Name="IsReadOnlyGlobal" Arg='name'/>
<Description>
returns <K>true</K> if the global variable named by the string <A>name</A> is
read-only and <K>false</K> otherwise (the default).
</Description>
</ManSection>
<ManSection>
<Func Name="MakeReadOnlyGlobal" Arg='name'/>
<Description>
marks the global variable named by the string <A>name</A> as read-only.
<P/>
A warning is given if <A>name</A> has no value bound to it or if it is
already read-only.
</Description>
</ManSection>
<ManSection>
<Func Name="MakeReadWriteGlobal" Arg='name'/>
<Description>
marks the global variable named by the string <A>name</A> as read-write.
<P/>
A warning is given if <A>name</A> is already read-write.
<P/>
<Log><![CDATA[
gap> xx := 17;
17
gap> IsReadOnlyGlobal("xx");
false
gap> xx := 15;
15
gap> MakeReadOnlyGlobal("xx");
gap> xx := 16;
Variable: 'xx' is read only
not in any function
Entering break read-eval-print loop ...
you can 'quit;' to quit to outer loop, or
you can 'return;' after making it writable to continue
brk> quit;
gap> IsReadOnlyGlobal("xx");
true
gap> MakeReadWriteGlobal("xx");
gap> xx := 16;
16
gap> IsReadOnlyGlobal("xx");
false
]]></Log>
</Description>
</ManSection>
<#Include Label="MakeConstantGlobal">
<ManSection>
<Func Name="ValueGlobal" Arg='name'/>
<Description>
returns the value currently bound to the global variable named by the
string <A>name</A>. An error is raised if no value is currently bound.
</Description>
</ManSection>
<ManSection>
<Func Name="IsBoundGlobal" Arg='name'/>
<Description>
returns <K>true</K> if a value currently bound
to the global variable named by the string <A>name</A> and <K>false</K> otherwise.
</Description>
</ManSection>
<ManSection>
<Func Name="UnbindGlobal" Arg='name'/>
<Description>
removes any value currently bound
to the global variable named by the string <A>name</A>. Nothing is returned.
<P/>
A warning is given if <A>name</A> was not bound. The global variable named
by <A>name</A> must be writable, otherwise an error is raised.
</Description>
</ManSection>
<#Include Label="BindGlobal">
<ManSection>
<Func Name="NamesGVars" Arg=''/>
<Description>
This function returns an immutable
(see <Ref Sect="Mutability and Copyability"/>)
sorted (see <Ref Sect="Sorted Lists and Sets"/>) list of all the global
variable names known to the system. This includes names of variables
which were bound but have now been unbound and some other names which
have never been bound but have become known to the system by various
routes.
</Description>
</ManSection>
<ManSection>
<Func Name="NamesSystemGVars" Arg=''/>
<Description>
This function returns an immutable sorted list of all the global
variable names created by the &GAP; library when &GAP; was started.
</Description>
</ManSection>
<ManSection>
<Func Name="NamesUserGVars" Arg=''/>
<Description>
This function returns an immutable sorted list of the global variable
names created since the library was read, to which a value is
currently bound.
</Description>
</ManSection>
<!-- here name spaces -->
</Section>
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Namespaces">
<Heading>Namespaces for &GAP; packages</Heading>
As mentioned in Section <Ref Sect="More About Global Variables"/>
above all global variables share a common namespace. This can
relatively easily lead to name clashes, in particular when many
&GAP; packages are loaded at the same time. To give package code
a way to have a package local namespace without breaking backward
compatibility of the &GAP; language, the following simple rule has
been devised:
<P/>
If in package code a global variable that ends with an
<Q>at</Q>-character <C>@</C> is accessed in any way, the name of the
package is appended before accessing it. Here, <Q>package code</Q>
refers to everything which is read with <Ref Func="ReadPackage"/>.
As the name of the package the entry <C>PackageName</C> in its
<F>PackageInfo.g</F> file is taken. As for all identifiers,
this name is case sensitive.
<P/>
For example, if the following is done in the code of a package with name
<C>xYz</C>:
<Log><![CDATA[
gap> a@ := 12;
]]>
</Log>
Then actually the global variable <C>a@xYz</C> is assigned. Further
accesses to <C>a@</C> within the package code will all be redirected
to <C>a@xYz</C>. This includes all the functions described in Section
<Ref Sect="More About Global Variables"/> and indeed all the functions
described Section <Ref Sect="Global Variables in the Library"/> like
for example <Ref Func="DeclareCategory"/>. Note that from code in the
same package it is still possible to access the same global variable
via <C>a@xYz</C> explicitly.
<P/>
All other code outside the package as well as interactive user input
that wants to refer to that variable <C>a@xYz</C> must do so explicitly
by using <C>a@xYz</C>.
<P/>
Since in earlier releases of &GAP; the <Q>at</Q>-character <C>@</C>
was not a legal character (without using backslashes), this small
extension of the language does not break any old code.
</Section>
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<Section Label="Function">
<Heading>Function</Heading>
<Index Subkey="definition of">functions</Index>
<Index Key="end"><K>end</K></Index>
<Index Key="local"><K>local</K></Index>
<Index>recursion</Index>
<Index Subkey="recursive">functions</Index>
<Index>environment</Index><Index>body</Index>
<C>function( [ <A>arg-ident</A> {, <A>arg-ident</A>} ] )</C>
<P/>
<C> [local <A>loc-ident</A> {, <A>loc-ident</A>} ; ]</C>
<P/>
<C> <A>statements</A></C>
<P/>
<C>end</C>
<P/>
A function
literal can be assigned to a variable or to a list element or a record
component.
Later this function can be called as described in <Ref Sect="Function Calls"/>.
<P/>
The following is an example of a function definition. It is a function
to compute values of the Fibonacci sequence (see <Ref Func="Fibonacci"/>).
<P/>
<Example><![CDATA[
gap> fib := function ( n )
> local f1, f2, f3, i;
> f1 := 1; f2 := 1;
> for i in [3..n] do
> f3 := f1 + f2;
> f1 := f2;
> f2 := f3;
> od;
> return f2;
> end;;
gap> List( [1..10], fib );
[ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
]]></Example>
<P/>
Because for each of the formal arguments <A>arg-ident</A> and for each of the
formal locals <A>loc-ident</A> a new variable is allocated when the function
is called (see <Ref Sect="Function Calls"/>),
it is possible that a function calls itself.
This is usually called <E>recursion</E>.
The following is a recursive function that computes values of the Fibonacci
sequence.
<P/>
<Example><![CDATA[
gap> fib := function ( n )
> if n < 3 then
> return 1;
> else
> return fib(n-1) + fib(n-2);
> fi;
> end;;
gap> List( [1..10], fib );
[ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
]]></Example>
<P/>
Note that the recursive version needs <C>2 * fib(<A>n</A>)-1</C> steps
to compute <C>fib(<A>n</A>)</C>,
while the iterative version of <C>fib</C> needs only <C><A>n</A>-2</C> steps.
Both are not optimal however, the library function <Ref Func="Fibonacci"/>
only needs about <C>Log(<A>n</A>)</C> steps.
<P/>
<Index Subkey="with a variable number of arguments">functions</Index>
<Index Key="arg" Subkey="special function argument"><C>arg</C></Index>
As noted in Section <Ref Sect="Function Calls"/>,
the case where a function's last argument is followed by <C>...</C> is special.
It provides a way of defining a function with a variable number of
arguments. The values of the actual arguments are computed and the
first ones are assigned to the new variables corresponding to the
formal arguments before the last argument, if any. The values of all the
remaining actual arguments are stored in a list
and this list is assigned to the new variable corresponding to the final formal
argument. There are two typical scenarios for wanting such a
possibility: having optional arguments and having any number of
arguments.
<P/>
The following example shows one way that the function
<Ref Oper="Position"/> might be encoded and demonstrates the
<Q>optional argument</Q> scenario.
<P/>
<Example><![CDATA[
gap> position := function ( list, obj, arg... )
> local pos;
> if 0 = Length(arg) then
> pos := 0;
> else
> pos := arg[1];
> fi;
> repeat
> pos := pos + 1;
> if pos > Length(list) then
> return fail;
> fi;
> until list[pos] = obj;
> return pos;
> end;
function( list, obj, arg... ) ... end
gap> position([1, 4, 2], 4);
2
gap> position([1, 4, 2], 3);
fail
gap> position([1, 4, 2], 4, 2);
fail
]]></Example>
<P/>
The following example demonstrates the <Q>any number of arguments</Q>
scenario.
<P/>
<Example><![CDATA[
gap> sum := function ( l... )
> local total, x;
> total := 0;
> for x in l do
> total := total + x;
> od;
> return total;
> end;
function( l... ) ... end
gap> sum(1, 2, 3);
6
gap> sum(1, 2, 3, 4);
10
gap> sum();
0
]]></Example>
<P/>
The user should compare the above with the &GAP; function <Ref Func="Sum"/>
which, for example, may take a list argument and optionally
an initial element (which zero should the sum of an empty list return?).
<P/>
GAP will also special case a function with a single argument with the name
<C>arg</C> as function with a variable length list of arguments, as if the
user had written <C>arg...</C>.
<P/>
Note that if a function <A>f</A> is defined as above