--- id: loops title: Loops --- ## General Iteration General iteration in PascaLIGO takes the shape of general loops, which should be familiar to programmers of imperative languages as "while loops". Those loops are of the form `while `. Their associated block is repeatedly evaluated until the condition becomes true, or never evaluated if the condition is false at the start. The loop never terminates if the condition never becomes true. Because we are writing smart contracts on Tezos, when the condition of a "while" loops fails to become true, the execution will run out of gas and stop with a failure anyway. Here is how to compute the greatest common divisors of two natural number by means of Euclid's algorithm: ```pascaligo group=a function gcd (var x : nat; var y : nat) : nat is block { if x < y then block { const z : nat = x; x := y; y := z } else skip; var r : nat := 0n; while y =/= 0n block { r := x mod y; x := y; y := r } } with x ``` You can call the function `gcd` defined above using the LIGO compiler like so: ```shell ligo run-function gitlab-pages/docs/language-basics/src/loops/gcd.ligo gcd '(2n*2n*3n*11n, 2n*2n*2n*3n*3n*5n*7n)' # Outputs: +12 ``` CameLIGO is a functional language where user-defined values are constant, therefore it makes no sense in CameLIGO to feature loops, which we understand as syntactic constructs where the state of a stopping condition is mutated, as with "while" loops in PascaLIGO. Instead, CameLIGO features a *fold operation* as a predefined function named `Loop.fold_while`. It takes an initial value of a certain type, called an *accumulator*, and repeatedly calls a given function, called *iterated function*, that takes that accumulator and returns the next value of the accumulator, until a condition is met and the fold stops with the final value of the accumulator. The iterated function needs to have a special type: if the type of the accumulator is `t`, then it must have the type `bool * t` (not simply `t`). It is the boolean value that denotes whether the stopping condition has been reached. Here is how to compute the greatest common divisors of two natural number by means of Euclid's algorithm: ```cameligo group=a let iter (x,y : nat * nat) : bool * (nat * nat) = if y = 0n then false, (x,y) else true, (y, x mod y) let gcd (x,y : nat * nat) : nat = let x,y = if x < y then y,x else x,y in let x,y = Loop.fold_while iter (x,y) in x ``` To ease the writing and reading of the iterated functions (here, `iter`), two predefined functions are provided: `continue` and `stop`: ```cameligo group=a let iter (x,y : nat * nat) : bool * (nat * nat) = if y = 0n then stop (x,y) else continue (y, x mod y) let gcd (x,y : nat * nat) : nat = let x,y = if x < y then y,x else x,y in let x,y = Loop.fold_while iter (x,y) in x ``` You can call the function `gcd` defined above using the LIGO compiler like so: ```shell ligo run-function gitlab-pages/docs/language-basics/src/loops/gcd.mligo gcd (2n*2n*3n*11n, 2n*2n*2n*3n*3n*5n*7n)' # Outputs: +12 ``` ReasonLIGO is a functional language where user-defined values are constant, therefore it makes no sense in ReasonLIGO to feature loops, which we understand as syntactic constructs where the state of a stopping condition is mutated, as with "while" loops in PascaLIGO. Instead, ReasonLIGO features a *fold operation* as a predefined function named `Loop.fold_while`. It takes an initial value of a certain type, called an *accumulator*, and repeatedly calls a given function, called *iterated function*, that takes that accumulator and returns the next value of the accumulator, until a condition is met and the fold stops with the final value of the accumulator. The iterated function needs to have a special type: if the type of the accumulator is `t`, then it must have the type `bool * t` (not simply `t`). It is the boolean value that denotes whether the stopping condition has been reached. Here is how to compute the greatest common divisors of two natural number by means of Euclid's algorithm: ```reasonligo group=a let iter = ((x,y) : (nat, nat)) : (bool, (nat, nat)) => if (y == 0n) { (false, (x,y)); } else { (true, (y, x mod y)); }; let gcd = ((x,y) : (nat, nat)) : nat => { let (x,y) = if (x < y) { (y,x); } else { (x,y); }; let (x,y) = Loop.fold_while (iter, (x,y)); x }; ``` To ease the writing and reading of the iterated functions (here, `iter`), two predefined functions are provided: `continue` and `stop`: ```reasonligo group=b let iter = ((x,y) : (nat, nat)) : (bool, (nat, nat)) => if (y == 0n) { stop ((x,y)); } else { continue ((y, x mod y)); }; let gcd = ((x,y) : (nat, nat)) : nat => { let (x,y) = if (x < y) { (y,x); } else { (x,y); }; let (x,y) = Loop.fold_while (iter, (x,y)); x }; ``` ## Bounded Loops In addition to general loops, PascaLIGO features a specialised kind of *loop to iterate over bounded intervals*. These loops are familiarly known as "for loops" and they have the form `for to `, which is familiar for programmers of imperative languages. Consider how to sum integers from `0` to `n`: ```pascaligo group=c function sum (var n : nat) : int is block { var acc : int := 0; for i := 1 to int (n) block { acc := acc + i } } with acc ``` (Please do not use that function: there exists a closed form formula.) You can call the function `sum` defined above using the LIGO compiler like so: ```shell ligo run-function gitlab-pages/docs/language-basics/src/loops/sum.ligo sum 7n # Outputs: 28 ``` PascaLIGO "for" loops can also iterate through the contents of a collection, that is, a list, a set or a map. This is done with a loop of the form `for in `, where ` value` (or any other variables). Give a map from strings to integers, here is how to sum all the integers and concatenate all the strings. You can call the function `sum_map` defined above using the LIGO compiler like so: ```shell ligo run-function gitlab-pages/docs/language-basics/src/loops/collection.ligo sum_map 'map ["1"->1; "2"->2; "3"->3]' # Outputs: ( "123", 6 ) ```