Functions and Loops¶
To define a function we specify the argument, variable and the
operation(s) performed on the argument. The software then tells us
what type of output the function gives. We can also ask the software
what type of input and output has been specified for the function
f
. For example:
atlas> set f(int x)=x^2
Defined f: (int->int)
atlas> whattype f?
Overloaded instances of 'f'
int->int
atlas> f(2)
Value: 4
atlas>
We can also specify what the output will be by including it in the definition of the function rather than expecting the software to decide what it would be:
atlas> set f(int x)=int:x^2
Redefined f: (int->int)
atlas>
atlas> set f(int x, int y)=rat:x/y
Added definition [2] of f: (int,int->rat)
atlas> f(3,2)
Value: 3/2
atlas>
More functions are defined in the .at
files and we can copy and paste more complicated functions from there.
In addition, for a quick search, recall that the atlas library within this doccumentation lists all the functions already available.
Arguments and Outputs¶
To find out about the usage of a function you type whattype
<function name> ?
. atlas
will list all the instances where that
function is used with the type of input and output for each case. For
example,:
atlas> whattype inverse ?
Overloaded instances of 'inverse'
mat->mat
atlas>
Gives you the argument and output for the function inverse
. It
says that the function takes a matrix and produces another matrix.
Note: Remember that the command whattype
without the question mark
gives a data type. To get atlas to give you an argument you need to
add the ?
atlas> whattype invert ?
Overloaded instances of 'invert'
mat->(mat,int)
atlas>
This says that the function invert
takes a matrix and gives back a pair of a matrix and an integer (See the section on Matrices for more information).
To find all usages of the function +
we do:
atlas> whattype + ?
Overloaded instances of '+'
(int,int)->int
(rat,int)->rat
(rat,rat)->rat
(vec,vec)->vec
(ratvec,ratvec)->ratvec
(mat,int)->mat
(int,mat)->mat
(mat,mat)->mat
(Split,Split)->Split
(ParamPol,Param)->ParamPol
(ParamPol,(Split,Param))->ParamPol
(ParamPol,[(Split,Param)])->ParamPol
(ParamPol,ParamPol)->ParamPol
(string,string)->string
(string,int)->string
(int,string)->string
(string,(int,int))->string
Split->int
([[vec]],[[vec]])->[[vec]]
([[vec]],vec)->[[vec]]
((Param,string),(Param,string))->(ParamPol,string)
((ParamPol,string),(Param,string))->(ParamPol,string)
((ParamPol,string),(ParamPol,string))->(ParamPol,string)
atlas>
Another command that tells us more about function usage for a given
input is the command @
, which we use in the following
format. Suppose we want to know what the function inverse does to a
matrix. Then we type:
atlas> inverse@mat
Value: Function defined at atlas-scripts/basic.at:254:4--256:74
(M): let (inv,d)=invert@mat(M) in if =@(int,int)(d,1) then inv else
error("Matrix not invertible over the integers") fi
atlas>
Note that it also tells you in which .at
file you can find the script
of the function
atlas> +@(string,string)
Value: Function defined at atlas-scripts/basic.at:108:0-70
(s,t): #@(string,string)(s,t)
atlas>
This is defined in basic, takes a pair of strings and concatenates them.
However, if you want to know what ‘+’ does to a matrix and an integer you get:
atlas> +@(mat,int)
Value: {+@(mat,int)}
atlas>
This means this is a built-in function that you can find in the
atlas-functions.help
file for information. But, in this case we
can also try it to see what it does:
atlas> set A =id_mat(3)
Identifier A: mat
atlas> A
Value:
| 1, 0, 0 |
| 0, 1, 0 |
| 0, 0, 1 |
atlas> {A quick way to write the nxn id. matrix}
atlas>
atlas> +(A,1)
Value:
| 2, 0, 0 |
| 0, 2, 0 |
| 0, 0, 2 |
atlas>
atlas> set A=mat:[[1,0,0],[0,2,0],[1,1,0]]
Variable A: mat (overriding previous instance, which had type mat)
atlas> +(A,1)
Value:
| 2, 0, 1 |
| 0, 3, 1 |
| 0, 0, 1 |
atlas> A
Value:
| 1, 0, 1 |
| 0, 2, 1 |
| 0, 0, 0 |
atlas>
In other words, the function +(A,1)
adds a 1 to the diagonal of the matrix A
.
Loops¶
Some of the simplest examples of loops are the for loops
. For example:
atlas> for i:3 do i od
Value: [0,1,2]
atlas>
atlas> set v=for i:3 do i od
Variable v: [int]
atlas> v
Value: [0,1,2]
Here od
tells atlas
to end the loop once all the vectors of A
were listed.
If we do not want atlas
to print the result we can
use either void:
before the loop or ;()
at the end of the
loop:
atlas> void:for i:3 do i od
atlas>
atlas> for i:3 do i od;()
atlas>
A loop can also be used to ask atlas to print from a list. For example:
atlas> for i:3 do prints(i) od
0
1
2
Value: [(),(),()]
atlas>
You can ignore the last line or use the commands above to prevent it from appearing:
atlas> void:for i:3 do prints(i) od
0
1
2
atlas> for i:3 do prints(i) od;()
0
1
2
Functions defined using loops¶
We can define some functions using loops. For example, one basic loop lists the column vectors of a matrix as follows:
atlas> A:=[[1,2],[3,4]]
Value:
| 1, 3 |
| 2, 4 |
atlas>
atlas> for v in A do v od
Value: [[ 1, 2 ],[ 3, 4 ]]
atlas>
This is an example of a for loop
. Which tells the software that
for each v in A you return something.
Another example is:
atlas> v:=[1,2,3,4]
Value: [1,2,3,4]
atlas> for a in v do a^2 od
atlas>
Value: [1,4,9,16]
atlas> whattype $
type: [int]
atlas>
Which takes the elements of v, squares them and lists them as an array of integers.
Now using this type of simple for loop
we can, for example, define
the “flattening” function which takes the columns of a matrix and
writes them concatenated into a single row:
atlas> set f(mat A)=vec: let rv=vec:[] in for v in A do rv#:=v od;rv
Added definition [3] of f: (mat->vec)
atlas> A:=[[1,2],[3,4]]
Value:
| 1, 3 |
| 2, 4 |
atlas> f(A)
Value: [ 1, 2, 3, 4 ]
atlas>
Again the command above is a loop. The first part
says that the function takes a matrix and outputs a vector. The
second part defines an empty vector rv
. The third part is the loop that
says that for each vector v in the matrix A, append it to what you
have in rv
. The last part says, do it for all the vectors in A and print the final result.
Note the use of the operation #
here means append each v
in A
to the previous iteration.
You can find out more about this operation by typing whattype # ?
and by looking at the atlas-functions.help
file:
atlas> whattype # ?
Overloaded instances of '#'
(string,string)->string
string->int
vec->int
mat->(int,int)
(vec,int)->vec
(int,vec)->vec
(vec,vec)->vec
(int,[vec])->mat
LieType->int
Block->int
ParamPol->int
Here is a simple example of what you can do with it:
atlas> set v=vec:[1,2]
Identifier v: vec
atlas> set x=3
Identifier x: int
atlas> v#x
Value: [ 1, 2, 3 ]
atlas>
There are several kinds of loops which are explained in the
atlas.help
file. However, sometimes it is easier to look at some
of the scripts in the .at
files and see how the loops are used to
define functions. In particular the basic.at
file can be useful.