ligo/gitlab-pages/docs/reference/set.md

5.5 KiB

id title
set-reference Sets — Unordered unique collection of a type

Sets are unordered collections of values of the same type, like lists are ordered collections. Like the mathematical sets and lists, sets can be empty and, if not, elements of sets in LIGO are unique, whereas they can be repeated in a list.

Empty Sets

const my_set : set (int) = set []
let my_set : int set = Set.empty
let my_set : set (int) = Set.empty;

Non-empty Sets

const my_set : set (int) = set [3; 2; 2; 1]
let my_set : int set =
  Set.add 3 (Set.add 2 (Set.add 2 (Set.add 1 (Set.empty : int set))))
let my_set : set (int) =
  Set.add (3, Set.add (2, Set.add (2, Set.add (1, Set.empty : set (int)))));

Set Membership

const contains_3 : bool = my_set contains 3
let contains_3 : bool = Set.mem 3 my_set
let contains_3 : bool = Set.mem (3, my_set);

Cardinal of Sets

The predefined function Set.size returns the number of elements in a given set as follows.

const cardinal : nat = Set.size (my_set)

Note that size is deprecated.

let cardinal : nat = Set.size my_set
let cardinal : nat = Set.size (my_set);

Updating Sets

There are two ways to update a set, that is to add or remove from it.

In PascaLIGO, either we create a new set from the given one, or we modify it in-place. First, let us consider the former way:

const larger_set  : set (int) = Set.add (4, my_set)
const smaller_set : set (int) = Set.remove (3, my_set)

Note that set_add and set_remove are deprecated.

If we are in a block, we can use an instruction to modify the set bound to a given variable. This is called a patch. It is only possible to add elements by means of a patch, not remove any: it is the union of two sets.

function update (var s : set (int)) : set (int) is block {
  patch s with set [4; 7]
} with s

const new_set : set (int) = update (my_set)
let larger_set  : int set = Set.add 4 my_set
let smaller_set : int set = Set.remove 3 my_set
let larger_set  : set (int) = Set.add (4, my_set);
let smaller_set : set (int) = Set.remove (3, my_set);

Functional Iteration over Sets

A functional iterator is a function that traverses a data structure and calls in turn a given function over the elements of that structure to compute some value. Another approach is possible in PascaLIGO: loops (see the relevant section).

There are three kinds of functional iterations over LIGO maps: the iterated operation, the mapped operation (not to be confused with the map data structure) and the folded operation.

Iterated Operation

The first, the iterated operation, is an iteration over the map with no return value: its only use is to produce side-effects. This can be useful if for example you would like to check that each value inside of a map is within a certain range, and fail with an error otherwise.

function iter_op (const s : set (int)) : unit is
  block {
    function iterated (const i : int) : unit is
      if i > 2 then Unit else (failwith ("Below range.") : unit)
  } with Set.iter (iterated, s)

Note that set_iter is deprecated.

let iter_op (s : int set) : unit =
  let predicate = fun (i : int) -> assert (i > 3)
  in Set.iter predicate s
let iter_op = (s : set (int)) : unit => {
  let predicate = (i : int) => assert (i > 3);
  Set.iter (predicate, s);
};

Folded Operation

A folded operation is the most general of iterations. The folded function takes two arguments: an accumulator and the structure element at hand, with which it then produces a new accumulator. This enables having a partial result that becomes complete when the traversal of the data structure is over.

function sum (const acc : int; const i : int): int is acc + i
const sum_of_elements : int = Set.fold (sum, my_set, 0)

Note that set_fold is deprecated.

It is possible to use a loop over a set as well.

function loop (const s : set (int)) : int is block {
  var sum : int := 0;
  for element in set s block {
    sum := sum + element
  }
} with sum
let sum (acc, i : int * int) : int = acc + i
let sum_of_elements : int = Set.fold sum my_set 0
let sum = ((acc, i) : (int, int)) : int => acc + i;
let sum_of_elements : int = Set.fold (sum, my_set, 0);