Iteration
General Iteration
CameLIGO is a functional language where user-defined values are constant, therefore the preferred way to write iterations is by means of recursive functions. Here is how to compute the greatest common divisors of two natural numbers by means of Euclid's algorithm:
let rec iter (x, y : nat * nat) : nat =
if y = 0n then x else iter (y, x mod y)
let gcd (x, y : nat * nat) : nat =
let x, y = if x < y then y,x else x,y
in iter (x, y)
You can call the function gcd
defined above using the LIGO compiler
like so:
ligo run evaluate-call \
gitlab-pages/docs/language-basics/src/loops/gcd.mligo \
gcd '(2n*2n*3n*11n, 2n*2n*2n*3n*3n*5n*7n)'
# Outputs: +12
CameLIGO also features loops, which we understand as syntactic constructs where the state of a stopping condition is mutated. There are two kinds of loops: for-loops and while-loops. Here is again Euclid's algorithm, but using mutation and a while-loop:
let gcd (a, b : nat * nat) =
let mut x, y = a, b in // we will modify x and y
let () =
if x < y then
let z = x in
begin
x := y; y := z
end in
let mut r : nat = 0n in
let () =
while y <> 0n do
r := x mod y;
x := y;
y := r
done
in x
Here is how to check if a string is a palindrome or not using a for
loop:
let get_char s idx = String.sub idx 1n s
let is_palindrome s =
let mut p = "" in
let length = String.length s in
let () =
for i = length - 1 downto 0 do
p := p ^ get_char s (abs i)
done
in p = s
JsLIGO currently supports iteration through while-loops, for-loops, and through the use of tail recursive functions.
Here is how to check if a string is a palindrome or not using a for
loop:
const getChar = (s: string, idx: nat): string => String.sub(idx, 1n, s);
function isPalindrome (s: string): bool {
let p = "";
let length = String.length(s);
for (let i = length - 1 ; i >= 0 ; i--)
p += getChar(s, abs(i));
return p == s;
};
Here is how to compute the greatest common divisors of two natural numbers by means of Euclid's algorithm with using a while loop:
function gcd (a: nat, b: nat) {
let [x,y] = [a,b]; // we will modify x and y
if (x < y) {
const z = x;
x = y; y = z;
}
let r: nat = 0n
while (y != 0n) {
r = x % y;
x = y;
y = r;
}
return x;
};
And here is how to compute the greatest common divisors of two natural numbers by means of Euclid's algorithm using tail recursion:
function iter (x: nat,y: nat): nat {
if (y == 0n) return x else return iter (y, x % y)
};
function gcd2 (x: nat,y: nat) : nat {
if (x < y) return iter (y, x) else return iter (x, y)
};
You can call the function gcd
defined above using the LIGO compiler
like so:
ligo run evaluate-expr \
gitlab-pages/docs/language-basics/src/loops/gcd.jsligo \
'gcd(2n*2n*3n*11n, 2n*2n*2n*3n*3n*5n*7n)'
# Outputs: +12
and can call the function gcd2
defined above using the LIGO compiler
like so:
ligo run evaluate-expr \
gitlab-pages/docs/language-basics/src/loops/gcd.jsligo \
'gcd2(2n*2n*3n*11n, 2n*2n*2n*3n*3n*5n*7n)'
# Outputs: +12
Note: Currently JsLIGO does not support the key words
break
&continue
in the context of loops.
for-of Loops
JsLIGO "for-of" loops can 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 (const <element var> of <collection var>) <block>
.
Here is an example where the integers in a list are summed up.
function sum_list (l : list<int>) {
let total = 0;
for (const i of l) total = total + i;
return total;
};
You can call the function sum_list
defined above using the LIGO compiler
like so:
ligo run evaluate-expr \
gitlab-pages/docs/language-basics/src/loops/collection.jsligo \
'sum_list(list([1,2,3]))'
# Outputs: 6
Here is an example where the integers in a set are summed up.
function sum_set (s : set<int>) {
let total : int = 0;
for (const i of s) total = total + i;
return total;
};
You can call the function sum_set
defined above using the LIGO compiler
like so:
ligo run evaluate-expr \
gitlab-pages/docs/language-basics/src/loops/collection.jsligo \
'sum_set(Set.literal(list([1,2,2,3])))'
# Outputs: 6
Loops over maps are actually loops over the bindings of the map. Given a map from strings to integers, here is how to sum all the integers and concatenate all the strings.
function sum_map (m: map<string, int>) {
let string_total = ""
let int_total = 0
for (const item of m) {
let [key, value] = item;
string_total = string_total + key;
int_total = int_total + value
}
return [string_total, int_total]
}
You can call the function sum_map
defined above using the LIGO compiler
like so:
ligo run evaluate-expr \
gitlab-pages/docs/language-basics/src/loops/collection.jsligo \
'sum_map(Map.literal(list([ ["1", 1], ["2", 2], ["3", 3] ])))'
# Outputs: ( "123", 6 )