Composed Types

Option

Options represents a value that could be defined Some(value) or not None.

const a: nat option = None;
const b: nat option = Some(12n);

The option type offers some helpers:

const c: bool = isNone(a); // returns true if a is None
const d: bool = isSome(a); // returns true if a is Some(_)
const e: nat = getSome(b): // extract the value (if any) or fail

List

List type represents list of same-type elements; a list can be declared as follow:

let l: nat list = (List.empty(): nat list); // empty list
let l1: nat list = [12n, 13n]; // literal list
let ls: nat = l.size();
let lh: nat = l.head();
let lt: nat list = l.tail();
let l2: nat list = l.prepend(14n);
let l3: nat list = l.mapWith((a: nat) => (a * 2n));
let l4: nat list = l.filter((a: nat) => (a <= 13n));

prepend, mapWith and filter are applied in-place if used over storage fields. Their types are unit instead of nat list. To apply as expression, surround the storage field with copy().

Set

Sets are list of different elements of the same-type.

let s: nat set = (Set.empty(): nat set); // empty set
let s1: nat set = ([12n, 13n]: nat set); // literal set
let ss: nat = s.size();
let b: bool = s.mem(13n);
let s2: nat set = s1.update(18n, true); // add
let s2: nat set = s2.update(18n, false); // remove
let ssum: nat = s2.fold((acc: nat, l: nat) => (acc + l), 0n);

update are applied in-place if used over storage fields. Their types are unit instead of nat set. To apply as expression, surround the storage field with copy().

Tuple

A tuple is a pair, triple, etc of different types; you can define a tuple as follow:

let atuple: (int, string) = (12, "hello");

Record

Map & Big_map

('a, 'b) Map and ('a, 'b) Big_map are collections of 'b indexed by a key 'a; 'a should be a comparable.

update, remove, mapWith, fold, filter are applied in-place if used over storage fields. Their types are unit instead of nat set. To apply as expression, surround the storage field with copy().

Map

let m: (string, nat) map = (Map.empty(): (string, nat) map);
let m: (string, nat) map = [ { "Hello": 12 } ];
let a: nat = m.size();
let b: nat = m.get("Ciao", 0); // failsafe get
let b1: nat = m.get("Ciao"); // failable get
let c: nat option = m.getOpt("Ciao");
let b: bool = m.mem("Ciao");
let c: nat = m.fold((acc: nat, k: string, v: nat) => (acc+v), 0n);
let m2: (string, nat) map = m.mapWith((k: string, v: nat) => (v * 2n)); 
let m2: (string, nat) map = m.filter((k: string, v: nat) => (v > 2n)); 
let m2: (string, nat) map = m.remove("Hello"); 
let m2: (string, nat) map = m.update("Hello", 42n); 

Big_map

let bm: (string, nat) big_map = (BigMap.empty(): (string, nat) big_map);
let b: nat = bm.get("Ciao", 0); // failsafe get
let b1: nat = bm.get("Ciao"); // failable get
let c: nat option = bm.getOpt("Ciao");
let b: bool = bm.mem("Ciao");
let bm2: (string, nat) big_map = m.remove("Hello"); 
let bm2: (string, nat) big_map = bm.update("Hello", 42n); 

Lambda

Lambda type represent anonymous functions.

const e_sum: int -> int = (a: int) => (0 + 1);
const e_gt: int -> bool = (a: int) => (0 > 1);
const e_gt2: int -> bool = (a: int) => (a > 1);
const e_comp: (int, int) -> bool = (a: int, b: int) => ((a * 8) > (b - 12));
const e_comp2: (int, int) -> bool = (a: int, b: int) => ((a * (b - 8)) > (b - 12));
const e_apply: int -> bool = (a: int) => (e_comp (12, 13));

const e_apply2: int -> int = (a: int) => (((b: int) => (b))(12));
const e_apply3: int -> int = (a: int) => (e_apply2 (12));

In-place modification

While calling some of the composed type specific functions, if the left-hand is storage field, the modification will be automatically assigned to the field storage.

this.flist.prepend (12n); // this has type unit, an modify flist prepending 12n

To avoid this behaviour, you can use the copy helper function.

let a: nat list = copy(this.flist).prepend(12n);

Last updated