More updates to the documentation. Synced the new reference page.

This commit is contained in:
Christian Rinderknecht 2020-02-26 18:31:58 +01:00
parent 1522a7d2e4
commit 127a85822f
8 changed files with 694 additions and 680 deletions

View File

@ -458,8 +458,7 @@ let force_access = ((key, moves) : (address, register)) : move => {
### Updating a Map ### Updating a Map
Given a map, we may want to add a new binding, remove one, or modify Given a map, we may want to add a new binding, remove one, or modify
one by changing the value associated to an already existing key. We one by changing the value associated to an already existing key. All
may even want to retain the key but not the associated value. All
those operations are called *updates*. those operations are called *updates*.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
@ -733,21 +732,18 @@ Here is how we define a big map:
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=big_maps ```pascaligo group=big_maps
type move is int * int type move is int * int
type register is big_map (address, move) type register is big_map (address, move)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=big_maps ```cameligo group=big_maps
type move = int * int type move = int * int
type register = (address, move) big_map type register = (address, move) big_map
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=big_maps ```reasonligo group=big_maps
type move = (int, int); type move = (int, int);
type register = big_map (address, move); type register = big_map (address, move);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -789,9 +785,9 @@ const moves : register =
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)] ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
``` ```
Notice the right arrow `->` between the key and its value and the --> Notice the right arrow `->` between the key and its value and the
semicolon separating individual map entries. The value annotation --> semicolon separating individual map entries. The value annotation
`("<string value>" : address)` means that we cast a string into an --> `("<string value>" : address)` means that we cast a string into an
address. --> address. -->
<!--CameLIGO--> <!--CameLIGO-->

View File

@ -213,7 +213,7 @@ let c : tez = 5n * 5mutez;
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Division ## Euclidean Division
In LIGO you can divide `int`, `nat`, and `tez`. Here is how: In LIGO you can divide `int`, `nat`, and `tez`. Here is how:
@ -243,6 +243,46 @@ let c : nat = 10mutez / 3mutez;
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
LIGO also allows you to compute the remainder of the Euclidean
division. In LIGO, it is a natural number.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=d
const a : int = 120
const b : int = 9
const rem1 : nat = a mod b // 3
const c : nat = 120n
const rem2 : nat = c mod b // 3
const d : nat = 9n
const rem3 : nat = c mod d // 3
const rem4 : nat = a mod d // 3
```
<!--CameLIGO-->
```cameligo group=d
let a : int = 120
let b : int = 9
let rem1 : nat = a mod b // 3
let c : nat = 120n
let rem2 : nat = c mod b // 3
let d : nat = 9n
let rem3 : nat = c mod d // 3
let rem4 : nat = a mod d // 3
```
<!--ReasonLIGO-->
```reasonligo group=d
let a : int = 120;
let b : int = 9;
let rem1 : nat = a mod b; // 3
let c : nat = 120n;
let rem2 : nat = c mod b; // 3
let d : nat = 9n;
let rem3 : nat = c mod d; // 3
let rem4 : nat = a mod d; // 3
```
## From `int` to `nat` and back ## From `int` to `nat` and back
You can *cast* an `int` to a `nat` and vice versa. Here is how: You can *cast* an `int` to a `nat` and vice versa. Here is how:
@ -265,7 +305,6 @@ let b : nat = abs (1)
let a : int = int (1n); let a : int = int (1n);
let b : nat = abs (1); let b : nat = abs (1);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Checking a `nat` ## Checking a `nat`

View File

@ -124,7 +124,6 @@ let my_list : list (int) = [1, 2, 2]; // The head is 1
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
### Adding to Lists ### Adding to Lists
Lists can be augmented by adding an element before the head (or, in Lists can be augmented by adding an element before the head (or, in
@ -176,15 +175,16 @@ There are three kinds of functional iterations over LIGO lists: the
*iterated operation*, the *map operation* (not to be confused with the *iterated operation*, the *map operation* (not to be confused with the
*map data structure*) and the *fold operation*. *map data structure*) and the *fold operation*.
#### Iterated Operation over Lists #### Iterated Operation over Lists
The first, the *iterated operation*, is an iteration over the list The first, the *iterated operation*, is an iteration over the list
with a unit return value. It is useful to enforce certain invariants with a unit return value. It is useful to enforce certain invariants
on the element of a list, or fail. For example you might want to check on the element of a list, or fail.
that each value inside of a list is within a certain range, and fail
otherwise. The predefined functional iterator implementing the For example you might want to check that each value inside of a list
iterated operation over lists is called `List.iter`. is within a certain range, and fail otherwise. The predefined
functional iterator implementing the iterated operation over lists is
called `List.iter`.
In the following example, a list is iterated to check that all its In the following example, a list is iterated to check that all its
elements (integers) are strictly greater than `3`. elements (integers) are strictly greater than `3`.
@ -305,7 +305,7 @@ let sum_of_elements : int = List.fold (sum, my_list, 0);
Sets are unordered collections of values of the same type, like lists Sets are unordered collections of values of the same type, like lists
are ordered collections. Like the mathematical sets and lists, sets are ordered collections. Like the mathematical sets and lists, sets
can be empty and, if not, elements of sets in LIGO are *unique*, can be empty and, if not, elements of sets in LIGO are *unique*,
whereas they can be repeated in a list. whereas they can be repeated in a *list*.
### Empty Sets ### Empty Sets
@ -447,6 +447,9 @@ elements in a given set as follows.
```pascaligo group=sets ```pascaligo group=sets
const cardinal : nat = Set.size (my_set) const cardinal : nat = Set.size (my_set)
``` ```
> Note that `size` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=sets ```cameligo group=sets
@ -636,12 +639,9 @@ traversal of the data structure is over. The predefined fold over sets
is called `Set.fold`. is called `Set.fold`.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=sets ```pascaligo group=sets
function sum (const acc : int; const i : int): int is acc + i function sum (const acc : int; const i : int): int is acc + i
const sum_of_elements : int = Set.fold (sum, my_set, 0) const sum_of_elements : int = Set.fold (sum, my_set, 0)
``` ```
@ -659,18 +659,14 @@ function loop (const s : set (int)) : int is block {
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=sets ```cameligo group=sets
let sum (acc, i : int * int) : int = acc + i let sum (acc, i : int * int) : int = acc + i
let sum_of_elements : int = Set.fold sum my_set 0 let sum_of_elements : int = Set.fold sum my_set 0
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=sets ```reasonligo group=sets
let sum = ((acc, i) : (int, int)) : int => acc + i; let sum = ((acc, i) : (int, int)) : int => acc + i;
let sum_of_elements : int = Set.fold (sum, my_set, 0); let sum_of_elements : int = Set.fold (sum, my_set, 0);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -1,60 +1,66 @@
--- ---
id: big-map-reference id: big-map-reference
title: Big Map — Scalable Maps title: Big Maps — Scalable Maps
--- ---
## Defining A Big Map Type Ordinary maps are fine for contracts with a finite lifespan or a
bounded number of users. For many contracts however, the intention is
to have a map holding *many* entries, potentially millions of
them. The cost of loading those entries into the environment each time
a user executes the contract would eventually become too expensive
were it not for *big maps*. Big maps are a data structure offered by
Michelson which handles the scaling concerns for us. In LIGO, the
interface for big maps is analogous to the one used for ordinary maps.
# Declaring a Map
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--PascaLIGO-->
```pascaligo group=big_map ```pascaligo group=big_maps
type move is int * int type move is int * int
type register is big_map (address, move) type register is big_map (address, move)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=big_map ```cameligo group=big_maps
type move = int * int type move = int * int
type register = (address, move) big_map type register = (address, move) big_map
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=big_map ```reasonligo group=big_maps
type move = (int, int); type move = (int, int);
type register = big_map (address, move); type register = big_map (address, move);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Creating an Empty Big Map
Create an empty big map. # Creating an Empty Big Map
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=big_map ```pascaligo group=big_maps
const empty : register = big_map [] const empty : register = big_map []
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=big_map ```cameligo group=big_maps
let empty : register = Big_map.empty let empty : register = Big_map.empty
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=big_map ```reasonligo group=big_maps
let empty : register = Big_map.empty let empty : register = Big_map.empty
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Populating A Big Map # Creating a Non-empty Map
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=big_map <!--PascaLIGO-->
```pascaligo group=big_maps
const moves : register = const moves : register =
big_map [ big_map [
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2); ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
@ -62,8 +68,7 @@ const moves: register =
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=big_maps
```cameligo group=big_map
let moves : register = let moves : register =
Big_map.literal [ Big_map.literal [
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2));
@ -71,67 +76,42 @@ let moves: register =
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=big_maps
```reasonligo group=big_map
let moves : register = let moves : register =
Big_map.literal ([ Big_map.literal ([
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)), ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]); ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Retrieving a Value in a Big Map # Accessing Values
Retrieve the value associated with a particular key. This version
returns an option which can either shift logic in response to a
missing value or throw an error.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--PascaLIGO-->
```pascaligo group=big_map ```pascaligo group=big_maps
const my_balance : option (move) = const my_balance : option (move) =
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=big_maps
The function is `Big_map.find_opt` whose type is `'key ->
('key,'value) big_map) -> 'value option`. Recall that the function
`Big_map.find_opt` must always be fully applied to its arguments. Here
is an example:
```cameligo group=big_map
let my_balance : move option = let my_balance : move option =
Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=big_maps
The function is `Big_map.find_opt` whose type is `('key, ('key,
'value) big_map) : 'value option`. Here is an example:
```reasonligo group=big_map
let my_balance : option (move) = let my_balance : option (move) =
Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves); Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Updating a Binding in a Big Map
Given a map, we may want to add a new binding, remove one, or modify # Updating Big Maps
one by changing the value associated to an already existing key. We
may even want to retain the key but not the associated value. All
those operations are called *updates*.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
<!--Pascaligo--> ```pascaligo group=big_maps
The values of a PascaLIGO big map can be updated using the ordinary
assignment syntax:
```pascaligo group=big_map
function add (var m : register) : register is function add (var m : register) : register is
block { block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9) m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
@ -140,114 +120,45 @@ function add (var m : register) : register is
const updated_map : register = add (moves) const updated_map : register = add (moves)
``` ```
See further for the removal of bindings. <!--CameLIGO-->
```cameligo group=big_maps
<!--Cameligo-->
In CameLIGO, you need the predefined function `Big_map.update` whose
type is `'key -> 'value option -> ('key, 'value) big_map -> ('key,
'value) big_map`. If the value (second argument) is `None`, then the
binding is to be removed. Recall that the function `Big_map.update`
must always be fully applied to its arguments. Here is an example:
```cameligo group=big_map
let updated_map : register = let updated_map : register =
Big_map.update Big_map.update
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves
``` ```
<!--Reasonligo--> <!--ReasonLIGO-->
```reasonligo group=big_maps
In ReasonLIGO, you need the predefined function `Big_map.update` whose
type is `('key, 'value option, ('key, 'value) big_map) : ('key,
'value) big_map`. If the value (second componenat) is `None`, then the
binding is to be removed. Here is an example:
```reasonligo group=big_map
let updated_map : register = let updated_map : register =
Big_map.update Big_map.update
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves); (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Adding a Binding to a Big Map # Removing Bindings
Add a key and its associated value to the big map.
<!--DOCUSAURUS_CODE_TABS-->
```pascaligo group=big_map
function add (var m : register) : register is
block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
} with m
const updated_map : register = add (moves)
```
<!--CameLIGO-->
In CameLIGO, we use the predefined function `Big_map.add`, whose type
is `'key -> 'value -> ('key, 'value) big_map -> ('key, 'value)
big_map`. Recall that the function `Big_map.add` must always be fully
applied to its arguments. Here is an example:
```cameligo group=big_map
let add (m : register) : register =
Map.add
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (4,9) m
```
<!--ReasonLIGO-->
In ReasonLIGO, we use the predefined function `Big_map.add`, whose
type is `('key, 'value, ('key, 'value) big_map : ('key, 'value)
big_map`. Here is an example:
```reasonligo group=big_map
let add = (m : register) : register =>
Map.add
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Removing a Binding from a Big Map
Remove a key and its associated value from the big map.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=big_map ```pascaligo group=big_maps
function delete (const key : address; var moves : register) : register is function rem (var m : register) : register is
block { block {
remove key from map moves remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) from map moves
} with moves } with m
const updated_map : register = rem (moves)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=big_maps
In CameLIGO, we use the predefined function `Big_map.remove` whose let updated_map : register =
type is `'key -> ('key, 'value) big_map -> ('key, 'value) Map.remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
big_map`. Note that, despite being curried, the calls to that function
must be complete. Here is an example:
```cameligo group=big_map
let delete (key, moves : address * register) : register =
Map.remove key moves
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=big_maps
In ReasonLIGO, we use the predefined function `Big_map.remove` whose let updated_map : register =
type is `('key, ('key, 'value) big_map) : ('key, 'value) Map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves)
big_map`. Here is an example:
```reasonligo group=big_map
let delete = ((key, moves) : (address, register)) : register =>
Map.remove (key, moves);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -1,9 +1,9 @@
--- ---
id: current-reference id: current-reference
title: Current - Things relating to the current execution context title: Tezos - Things relating to the current execution context
--- ---
## Current.balance() : tez # Tezos.balance
Get the balance for the contract. Get the balance for the contract.
@ -12,25 +12,35 @@ Get the balance for the contract.
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo
function main (const p : unit; const s: tez) : list (operation) * tez is function main (const p : unit; const s: tez) : list (operation) * tez is
((nil : list(operation)), balance) ((nil : list (operation)), Tezos.balance)
``` ```
> Note that `balance` and `Current.balance` are *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
let main (p, s : unit * tez) = let main (p,s : unit * tez) = ([] : operation list), Tezos.balance
([] : operation list), balance
``` ```
> Note that `balance` and `Current.balance` are *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo
let main = ((p,s): (unit, tez)) => ([]: list(operation), balance); let main = ((p,s) : (unit, tez)) =>
([]: list (operation), Tezos.balance);
``` ```
> Note that `balance` and `Current.balance` are *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Current.time() : timestamp ## Tezos.now
Returns the current time as a [unix timestamp](https://en.wikipedia.org/wiki/Unix_time). Returns the current time as a [unix timestamp](https://en.wikipedia.org/wiki/Unix_time).
In LIGO, timestamps are type compatible in operations with `int`(s). This lets you set e.g. time constraints for your smart contracts like this: In LIGO, timestamps are type compatible in operations with
integers. This lets you set for instance time constraints for your
smart contracts like this:
### Examples ### Examples
@ -38,118 +48,134 @@ In LIGO, timestamps are type compatible in operations with `int`(s). This lets y
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo group=b ```pascaligo group=b
const today: timestamp = now; const today: timestamp = Tezos.now;
const one_day: int = 86400; const one_day: int = 86_400;
const in_24_hrs: timestamp = today + one_day; const in_24_hrs: timestamp = today + one_day;
const some_date: timestamp = ("2000-01-01T10:10:10Z" : timestamp); const some_date: timestamp = ("2000-01-01T10:10:10Z" : timestamp);
const one_day_later: timestamp = some_date + one_day; const one_day_later: timestamp = some_date + one_day;
``` ```
> Note that `now` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=b ```cameligo group=b
let today: timestamp = Current.time let today: timestamp = Tezos.now
let one_day: int = 86400 let one_day: int = 86_400
let in_24_hrs: timestamp = today + one_day let in_24_hrs: timestamp = today + one_day
let some_date: timestamp = ("2000-01-01t10:10:10Z" : timestamp) let some_date: timestamp = ("2000-01-01t10:10:10Z" : timestamp)
let one_day_later: timestamp = some_date + one_day let one_day_later: timestamp = some_date + one_day
``` ```
> Note that `Current.time` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=b ```reasonligo group=b
let today: timestamp = Current.time; let today: timestamp = Tezos.now;
let one_day: int = 86400; let one_day: int = 86_400;
let in_24_hrs: timestamp = today + one_day; let in_24_hrs: timestamp = today + one_day;
let some_date: timestamp = ("2000-01-01t10:10:10Z" : timestamp); let some_date: timestamp = ("2000-01-01t10:10:10Z" : timestamp);
let one_day_later: timestamp = some_date + one_day; let one_day_later: timestamp = some_date + one_day;
``` ```
> Note that `Current.time` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
#### 24 hours ago #### 24 hours ago
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo group=c ```pascaligo group=c
const today: timestamp = now; const today: timestamp = Tezos.now;
const one_day: int = 86400; const one_day: int = 86_400;
const in_24_hrs: timestamp = today - one_day; const in_24_hrs: timestamp = today - one_day;
``` ```
> Note that `now` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=c ```cameligo group=c
let today: timestamp = Current.time let today: timestamp = Tezos.now
let one_day: int = 86400 let one_day: int = 86_400
let in_24_hrs: timestamp = today - one_day let in_24_hrs: timestamp = today - one_day
``` ```
> Note that `Current.time` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=c ```reasonligo group=c
let today: timestamp = Current.time; let today: timestamp = Tezos.now;
let one_day: int = 86400; let one_day: int = 86_400;
let in_24_hrs: timestamp = today - one_day; let in_24_hrs: timestamp = today - one_day;
``` ```
> Note that `Current.time` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
#### Comparing timestamps #### Comparing Timestamps
You can also compare timestamps using the same comparison operators as for numbers: You can also compare timestamps using the same comparison operators as
for numbers
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo group=c ```pascaligo group=c
const not_tommorow: bool = (now = in_24_hrs) const not_tommorow: bool = (Tezos.now = in_24_hrs)
``` ```
> Note that `now` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=c ```cameligo group=c
let not_tomorrow: bool = (Current.time = in_24_hrs) let not_tomorrow: bool = (Tezos.now = in_24_hrs)
``` ```
> Note that `Current.time` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=c ```reasonligo group=c
let not_tomorrow: bool = (Current.time == in_24_hrs); let not_tomorrow: bool = (Tezos.now == in_24_hrs);
``` ```
> Note that `Current.time` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Current.amount() : tez ## Amount
Get the amount of tez provided by the sender to complete this transaction. Get the amount of tez provided by the sender to complete this
transaction.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo
function check (const p: unit) : int is function threshold (const p : unit) : int is
begin if Tezos.amount = 100tz then 42 else 0
var result : int := 0;
if amount = 100tz then
result := 42
else
result := 0
end with result
``` ```
> Note that `amount` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
let check_ (p: unit) : int = if Current.amount = 100tz then 42 else 0 let threshold (p : unit) : int = if Tezos.amount = 100tz then 42 else 0
``` ```
> Note that `Current.amount` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo
let check_ = (p: unit) : int => let threshold = (p : unit) : int =>
if (Current.amount == 100tz) { if (Tezos.amount == 100tz) { 42; } else { 0; };
42;
}
else {
0;
};
``` ```
> Note that `Current.amount` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Current.sender() : address ## Sender
Get the address that initiated the current transaction. Get the address that initiated the current transaction.
@ -157,52 +183,67 @@ Get the address that initiated the current transaction.
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo
function main (const p: unit) : address is sender function main (const p : unit) : address is Tezos.sender
``` ```
> Note that `sender` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
let main (p: unit) : address = Current.sender let main (p: unit) : address = Tezos.sender
``` ```
> Note that `Current.sender` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo
let main = (p: unit) : address => Current.sender; let main = (p : unit) : address => Tezos.sender;
``` ```
> Note that `Current.sender` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Current.address(c: a' contract) : address
Get the address associated with a `contract`. ## Address
Get the address associated with a value of type `contract`.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo
function main (const p : key_hash) : address is block { function main (const p : key_hash) : address is block {
const c : contract(unit) = implicit_account(p) ; const c : contract (unit) = Tezos.implicit_account (p)
} with address(c) } with Tezos.address(c)
``` ```
> Note that `implicit_account` and `address` are *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
let main (p : key_hash) = let main (p : key_hash) =
let c : unit contract = Current.implicit_account p in let c : unit contract = Tezos.implicit_account p
Current.address c in Tezos.address c
``` ```
> Note that `Current.implicit_account` and `Current.address` are
> *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo
let main = (p : key_hash) : address => { let main = (p : key_hash) : address => {
let c : contract(unit) = Current.implicit_account(p) ; let c : contract (unit) = Tezos.implicit_account (p);
Current.address(c) ; Tezos.address (c);
}; };
``` ```
> Note that `Current.implicit_account` and `Current.address` are
> *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Current.self_address() : address ## Self Address
Get the address of the currently running contract. Get the address of the currently running contract.
@ -210,84 +251,116 @@ Get the address of the currently running contract.
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo
function main (const p: unit) : address is self_address function main (const p : unit) : address is Tezos.self_address
``` ```
> Note that `self_address` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
let main (p: unit) : address = Current.self_address let main (p : unit) : address = Tezos.self_address
``` ```
> Note that `Current.self_address` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo
let main = (p: unit): address => Current.self_address; let main = (p : unit) : address => Tezos.self_address;
``` ```
> Note that `Current.self_address` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Current.implicit_account(p: key_hash) : a' contract ## Implicit Account
Get the default contract associated with an on-chain keypair. This contract Get the default contract associated with an on-chain key-pair. This
doesn't execute code, instead it exists to receive money on behalf of a keys contract does not execute code, instead it exists to receive tokens on
owner. behalf of a key's owner.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo
function main (const kh: key_hash) : contract(unit) is implicit_account(kh) function main (const kh: key_hash) : contract (unit) is
Tezos.implicit_account (kh)
``` ```
> Note that `implicit_account` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
let main (kh: key_hash) : unit contract = Current.implicit_account kh let main (kh : key_hash) : unit contract = Tezos.implicit_account kh
``` ```
> Note that `Current.implicit_account` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo
let main = (kh: key_hash): contract(unit) => Current.implicit_account(kh); let main = (kh : key_hash): contract (unit) =>
Tezos.implicit_account (kh);
``` ```
> Note that `Current.implicit_account` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Current.source() : address ## Source
Get the _originator_ of the current transaction. That is, if a chain of transactions Get the _originator_ (address) of the current transaction. That is, if
led to the current execution get the address that began the chain. Not to be confused a chain of transactions led to the current execution get the address
with `Current.sender`, which gives the address of the contract or user which directly that began the chain. Not to be confused with `Tezos.sender`, which
caused the current transaction. gives the address of the contract or user which directly caused the
current transaction.
> ⚠️ > ⚠️ There are a few caveats you should keep in mind before using
> There are a few caveats you should keep in mind before using `SOURCE` over `SENDER`: > `Tezos.source` over `Tezos.sender`:
> >
> 1. SOURCE will never be a contract, so if you want to allow contracts (multisigs etc) to operate your contract, you need to use SENDER > 1. `Tezos.source` will never be a contract, so if you want to allow
> 2. https://vessenes.com/tx-origin-and-ethereum-oh-my/ -- in general it is somewhat unsafe to assume that SOURCE understands everything that's going to happen in a transaction. If SOURCE transfers to a malicious (or sufficiently attackable) contract, that contract might potentially transfer to yours, without SOURCE's consent. So if you are using SOURCE for authentication, you risk being confused. A good historical example of this is bakers paying out delegation rewards. Naive bakers did (and probably still do) just use tezos-client to transfer to whatever KT1 delegates they had, even if those KT1 were malicious scripts. > contracts (multisigs etc) to operate your contract, you need to
> use `Tezos.sender`
> 2. https://vessenes.com/tx-origin-and-ethereum-oh-my/ -- in general
> it is somewhat unsafe to assume that `Tezos.source` understands
> everything that is going to happen in a transaction. If
> `Tezos.source` transfers to a malicious (or sufficiently
> attackable) contract, that contract might potentially transfer to
> yours, without `Tezos.source`'s consent. So if you are using
> `Tezos.source` for authentication, you risk being confused. A
> good historical example of this is bakers paying out delegation
> rewards. Naive bakers did (and probably still do) just use
> tezos-client to transfer to whatever KT1 delegates they had, even
> if those KT1 were malicious scripts.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo
function main (const p: unit) : address is source function main (const p: unit) : address is Tezos.source
``` ```
> Note that `source` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
let main (p: unit) : address = Current.source let main (p : unit) : address = Tezos.source
``` ```
> Note that `Current.source` is *deprecated*.
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo
let main = (p: unit) : address => Current.source; let main = (p : unit) : address => Tezos.source;
``` ```
> Note that `Current.source` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Current.failwith(error_message: string) : a' ## Failwith
Cause the contract to fail with an error message. Cause the contract to fail with an error message.
> ⚠ Using this currently requires a type annotation on the failwith to unify it > ⚠ Using this currently requires in general a type annotation on the
> with the type of whatever other code branch it's on. > `failwith` call.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
@ -295,25 +368,20 @@ Cause the contract to fail with an error message.
```pascaligo ```pascaligo
function main (const p : int; const s : unit) : list (operation) * unit is function main (const p : int; const s : unit) : list (operation) * unit is
block { block {
if p > 10 then failwith("fail") else skip; if p > 10 then failwith ("Failure.") else skip
} }
with ((nil : list (operation)), s) with ((nil : list (operation)), s)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
let main (p,s: unit * unit) = let main (p,s : int * unit) = if p > 10 then failwith "Failure."
if true then failwith "This contract always fails" else ()
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo
let main = ((p,s): (unit, unit)) => let main = ((p,s) : (int, unit)) =>
if (true) { if (p > 10) { failwith ("Failure."); };
failwith("This contract always fails");
} else {
();
};
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -1,6 +1,6 @@
--- ---
id: list-reference id: list-reference
title: List — Linear Collections title: Lists — Linear Collections
--- ---
Lists are linear collections of elements of the same type. Linear Lists are linear collections of elements of the same type. Linear
@ -11,7 +11,7 @@ called the *head*, and the sub-list after the head is called the
*tail*. For those familiar with algorithmic data structure, you can *tail*. For those familiar with algorithmic data structure, you can
think of a list a *stack*, where the top is written on the left. think of a list a *stack*, where the top is written on the left.
## Defining Lists # Defining Lists
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
@ -34,7 +34,7 @@ let my_list : list (int) = [1, 2, 2]; // The head is 1
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
### Adding to Lists # Adding to Lists
Lists can be augmented by adding an element before the head (or, in Lists can be augmented by adding an element before the head (or, in
terms of stack, by *pushing an element on top*). terms of stack, by *pushing an element on top*).
@ -61,7 +61,7 @@ let larger_list : list (int) = [5, ...my_list]; // [5,1,2,2]
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
### Functional Iteration over Lists # Functional Iteration over Lists
A *functional iterator* is a function that traverses a data structure A *functional iterator* is a function that traverses a data structure
and calls in turn a given function over the elements of that structure and calls in turn a given function over the elements of that structure
@ -72,7 +72,7 @@ There are three kinds of functional iterations over LIGO lists: the
*iterated operation*, the *map operation* (not to be confused with the *iterated operation*, the *map operation* (not to be confused with the
*map data structure*) and the *fold operation*. *map data structure*) and the *fold operation*.
#### Iterated Operation over Lists ## Iterated Operation over Lists
The first, the *iterated operation*, is an iteration over the list The first, the *iterated operation*, is an iteration over the list
with a unit return value. It is useful to enforce certain invariants with a unit return value. It is useful to enforce certain invariants
@ -86,9 +86,13 @@ on the element of a list, or fail.
function iter_op (const l : list (int)) : unit is function iter_op (const l : list (int)) : unit is
block { block {
function iterated (const i : int) : unit is function iterated (const i : int) : unit is
if i > 2 then Unit else (failwith ("Below range.") : unit) if i > 3 then Unit else (failwith ("Below range.") : unit)
} with list_iter (iterated, l) } with List.iter (iterated, l)
``` ```
> Note that `list_iter` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=lists ```cameligo group=lists
@ -108,7 +112,7 @@ let iter_op = (l : list (int)) : unit => {
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
#### Mapped Operation over Lists ## Mapped Operation over Lists
We may want to change all the elements of a given list by applying to We may want to change all the elements of a given list by applying to
them a function. This is called a *map operation*, not to be confused them a function. This is called a *map operation*, not to be confused
@ -122,9 +126,11 @@ with the map data structure.
function increment (const i : int): int is i + 1 function increment (const i : int): int is i + 1
// Creates a new list with all elements incremented by 1 // Creates a new list with all elements incremented by 1
const plus_one : list (int) = list_map (increment, larger_list) const plus_one : list (int) = List.map (increment, larger_list)
``` ```
> Note that `list_map` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=lists ```cameligo group=lists
@ -144,7 +150,8 @@ let plus_one : list (int) = List.map (increment, larger_list);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
#### Folded Operation over Lists
## Folded Operation over Lists
A *folded operation* is the most general of iterations. The folded A *folded operation* is the most general of iterations. The folded
function takes two arguments: an *accumulator* and the structure function takes two arguments: an *accumulator* and the structure
@ -158,9 +165,11 @@ traversal of the data structure is over.
```pascaligo group=lists ```pascaligo group=lists
function sum (const acc : int; const i : int): int is acc + i function sum (const acc : int; const i : int): int is acc + i
const sum_of_elements : int = list_fold (sum, my_list, 0) const sum_of_elements : int = List.fold (sum, my_list, 0)
``` ```
> Note that `list_fold` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=lists ```cameligo group=lists
@ -176,7 +185,7 @@ let sum_of_elements : int = List.fold (sum, my_list, 0);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## List Length # List Length
Get the number of elements in a list. Get the number of elements in a list.
@ -187,6 +196,8 @@ Get the number of elements in a list.
function size_of (const l : list (int)) : nat is List.length (l) function size_of (const l : list (int)) : nat is List.length (l)
``` ```
> Note that `size` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo
let size_of (l : int list) : nat = List.length l let size_of (l : int list) : nat = List.length l
@ -198,112 +209,3 @@ let size_of = (l : list (int)) : nat => List.length (l);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## List.map(map_function: a' -> b', lst: a' list) : 'b list
Apply an operation defined by `map_function` to each element of a list
and return a list of the modified elements.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=b
function increment(const i: int): int is i + 1;
// Creates a new list with elements incremented by 1
const incremented_list: list(int) = list_map(increment, list 1; 2; 3; end );
```
<!--CameLIGO-->
```cameligo group=b
let increment (i: int) : int = i + 1
(* Creates a new list with elements incremented by 1 *)
let incremented_list: int list = List.map increment [1; 2; 3]
```
<!--ReasonLIGO-->
```reasonligo group=b
let increment = (i: int): int => i + 1;
(* Creates a new list with elements incremented by 1 *)
let incremented_list: list(int) = List.map(increment, [1, 2, 3]);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## List.iter(iter_function: a' -> unit, lst: a' list) : unit
Apply a side effecting function `iter_function` to each element of a list with no
return value. This is useful for asserting that each element of a list satisfies
a particular property.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo
function iter_op (const s : list(int)) : int is
begin
var r : int := 0 ;
function aggregate (const i : int) : unit is
begin
r := r + i ;
end with unit ;
list_iter(aggregate, s) ;
end with r
```
<!--CameLIGO-->
```cameligo
let iter_op (s : int list) : unit =
let do_nothing = fun (_: int) -> unit
in List.iter do_nothing s
```
<!--ReasonLIGO-->
```reasonligo
let iter_op = (s: list(int)): unit => {
let do_nothing = (z: int) => unit;
List.iter(do_nothing, s);
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
## List.fold(fold_function: (a' * a') -> a', lst: a' list, acc: a') : 'a
Combine the elements of a list into one value using the operation defined by
`fold_function'. For example, you could define summation by folding a list of
integers. Starting with some initial accumulator value `acc`, the fold:
1. Consumes an element of the list.
2. Passes the accumulator value to `fold_function` along with the element to produce
a new accumulated value.
3. The new accumulated value replaces the previous one.
4. IF there are still elements in the list go back to 1, ELSE return the accumulator
Summation would be defined then by using a `fold_function` that takes two integers and
adds them together. Each step of the fold would consume an element from the list
and add it to the total until you've summed over the list.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=b
function sum(const result: int; const i: int): int is result + i;
const sum_of_a_list: int = list_fold(sum, list 1; 2; 3; end, 0);
```
<!--CameLIGO-->
```cameligo group=b
let sum (result, i: int * int) : int = result + i
let sum_of_a_list: int = List.fold sum [1; 2; 3] 0
```
<!--ReasonLIGO-->
```reasonligo group=b
let sum = ((result, i): (int, int)): int => result + i;
let sum_of_a_list: int = List.fold(sum, [1, 2, 3], 0);
```
<!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -1,60 +1,62 @@
--- ---
id: map-reference id: map-reference
title: Map title: Maps
--- ---
## Defining A Map Type *Maps* are a data structure which associate values of the same type to
values of the same type. The former are called *key* and the latter
*values*. Together they make up a *binding*. An additional requirement
is that the type of the keys must be *comparable*, in the Michelson
sense.
# Declaring a Map
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=map <!--PascaLIGO-->
```pascaligo group=maps
type move is int * int type move is int * int
type register is map (address, move) type register is map (address, move)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=map ```cameligo group=maps
type move = int * int type move = int * int
type register = (address, move) map type register = (address, move) map
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=map ```reasonligo group=maps
type move = (int, int); type move = (int, int);
type register = map (address, move); type register = map (address, move);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Creating an Empty Map # Creating an Empty Map
Create an empty map.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=map ```pascaligo group=maps
const empty : register = map [] const empty : register = map []
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=map ```cameligo group=maps
let empty : register = Map.empty let empty : register = Map.empty
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=map ```reasonligo group=maps
let empty : register = Map.empty let empty : register = Map.empty
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Populating A Map # Creating a Non-empty Map
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--PascaLIGO-->
```pascaligo group=maps
```pascaligo group=map
const moves : register = const moves : register =
map [ map [
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2); ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
@ -62,8 +64,7 @@ const moves: register =
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=maps
```cameligo group=map
let moves : register = let moves : register =
Map.literal [ Map.literal [
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2)); (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2));
@ -71,141 +72,128 @@ let moves: register =
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=maps
```reasonligo group=map
let moves : register = let moves : register =
Map.literal ([ Map.literal ([
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)), ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]); ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Retrieving a Value in a Map # Accessing Map Bindings
Retrieve the value associated with a particular key. This version
returns an option which can either shift logic in response to a
missing value or throw an error.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--PascaLIGO-->
```pascaligo group=map ```pascaligo group=maps
const my_balance : option (move) = const my_balance : option (move) =
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=maps
The function is `Map.find_opt` whose type is `'key ->
('key,'value) map) -> 'value option`. Recall that the function
`Map.find_opt` must always be fully applied to its arguments. Here
is an example:
```cameligo group=map
let my_balance : move option = let my_balance : move option =
Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=maps
The function is `Map.find_opt` whose type is `('key, ('key,
'value) map) : 'value option`. Here is an example:
```reasonligo group=map
let my_balance : option (move) = let my_balance : option (move) =
Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves); Map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Updating a Binding in a Map Notice how the value we read is an optional value: this is to force
the reader to account for a missing key in the map. This requires
Given a map, we may want to add a new binding, remove one, or modify *pattern matching*.
one by changing the value associated to an already existing key. We
may even want to retain the key but not the associated value. All
those operations are called *updates*.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--PascaLIGO-->
```pascaligo group=maps
The values of a PascaLIGO map can be updated using the ordinary function force_access (const key : address; const moves : register) : move is
assignment syntax: case moves[key] of
Some (move) -> move
```pascaligo group=map | None -> (failwith ("No move.") : move)
function add (var m : register) : register is end
block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
} with m
const updated_map : register = add (moves)
```
See further for the removal of bindings.
<!--Cameligo-->
In CameLIGO, you need the predefined function `Map.update` whose
type is `'key -> 'value option -> ('key, 'value) map -> ('key,
'value) map`. If the value (second argument) is `None`, then the
binding is to be removed. Recall that the function `Map.update`
must always be fully applied to its arguments. Here is an example:
```cameligo group=map
let updated_map : register =
Map.update
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves
```
<!--Reasonligo-->
In ReasonLIGO, you need the predefined function `Map.update` whose
type is `('key, 'value option, ('key, 'value) map) : ('key,
'value) map`. If the value (second componenat) is `None`, then the
binding is to be removed. Here is an example:
```reasonligo group=map
let updated_map : register =
Map.update
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Adding a Binding to a Map
Add a key and its associated value to the map.
<!--DOCUSAURUS_CODE_TABS-->
```pascaligo group=map
function add (var m : register) : register is
block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
} with m
const updated_map : register = add (moves)
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=maps
let force_access (key, moves : address * register) : move =
match Map.find_opt key moves with
Some move -> move
| None -> (failwith "No move." : move)
```
In CameLIGO, we use the predefined function `Map.add`, whose type <!--ReasonLIGO-->
is `'key -> 'value -> ('key, 'value) map -> ('key, 'value) ```reasonligo group=maps
map`. Recall that the function `Map.add` must always be fully let force_access = ((key, moves) : (address, register)) : move => {
applied to its arguments. Here is an example: switch (Map.find_opt (key, moves)) {
| Some (move) => move
| None => failwith ("No move.") : move
}
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
```cameligo group=map # Updating a Map
Given a map, we may want to add a new binding, remove one, or modify
one by changing the value associated to an already existing key. All
those operations are called *updates*.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=maps
function assign (var m : register) : register is
block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
} with m
```
If multiple bindings need to be updated, PascaLIGO offers a *patch
instruction* for maps, similar to that for records.
```pascaligo group=maps
function assignments (var m : register) : register is
block {
patch m with map [
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (4,9);
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2)
]
} with m
```
<!--CameLIGO-->
```cameligo group=maps
let assign (m : register) : register =
Map.update
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) m
```
Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had
use `None` instead, that would have meant that the binding is removed.
As a particular case, we can only add a key and its associated value.
```cameligo group=maps
let add (m : register) : register = let add (m : register) : register =
Map.add Map.add
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (4,9) m ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (4,9) m
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=maps
let assign = (m : register) : register =>
Map.update
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), Some ((4,9)), m);
```
In ReasonLIGO, we use the predefined function `Map.add`, whose Notice the optional value `Some (4,9)` instead of `(4,9)`. If we had
type is `('key, 'value, ('key, 'value) map : ('key, 'value) use `None` instead, that would have meant that the binding is removed.
map`. Here is an example:
```reasonligo group=map As a particular case, we can only add a key and its associated value.
```reasonligo group=maps
let add = (m : register) : register => let add = (m : register) : register =>
Map.add Map.add
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m); (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m);
@ -213,14 +201,12 @@ let add = (m : register) : register =>
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Removing a Binding from a Map To remove a binding from a map, we need its key.
Remove a key and its associated value from the map.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=map ```pascaligo group=maps
function delete (const key : address; var moves : register) : register is function delete (const key : address; var moves : register) : register is
block { block {
remove key from map moves remove key from map moves
@ -228,47 +214,144 @@ function delete (const key : address; var moves : register) : register is
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=maps
In CameLIGO, we use the predefined function `Map.remove` whose
type is `'key -> ('key, 'value) map -> ('key, 'value)
map`. Note that, despite being curried, the calls to that function
must be complete. Here is an example:
```cameligo group=map
let delete (key, moves : address * register) : register = let delete (key, moves : address * register) : register =
Map.remove key moves Map.remove key moves
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=maps
In ReasonLIGO, we use the predefined function `Map.remove` whose
type is `('key, ('key, 'value) map) : ('key, 'value)
map`. Here is an example:
```reasonligo group=map
let delete = ((key, moves) : (address, register)) : register => let delete = ((key, moves) : (address, register)) : register =>
Map.remove (key, moves); Map.remove (key, moves);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Getting the Size of a Map
The size of a map is its number of bindings. # Functional Iteration over Maps
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 *map operation* (not to be confused with the
*map data structure*) and the *fold operation*.
## Iterated Operation over Maps
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.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo group=map
function size_of (const m : register) : nat is size (m) ```pascaligo group=maps
function iter_op (const m : register) : unit is
block {
function iterated (const i : address; const j : move) : unit is
if j.1 > 3 then Unit else (failwith ("Below range.") : unit)
} with Map.iter (iterated, m)
``` ```
> Note that `map_iter` is *deprecated*.
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=map
let size_of (m : register) : nat = Map.size m ```cameligo group=maps
let iter_op (m : register) : unit =
let predicate = fun (i,j : address * move) -> assert (j.0 > 3)
in Map.iter predicate m
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=map
let size_of = (m : register): nat => Map.size (m); ```reasonligo group=maps
let iter_op = (m : register) : unit => {
let predicate = ((i,j) : (address, move)) => assert (j[0] > 3);
Map.iter (predicate, m);
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Map Operations over Maps
We may want to change all the bindings of a map by applying to them a
function. This is called a *map operation*, not to be confused with
the map data structure. The predefined functional iterator
implementing the map operation over maps is called `Map.map`.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=maps
function map_op (const m : register) : register is
block {
function increment (const i : address; const j : move) : move is
(j.0, j.1 + 1)
} with Map.map (increment, m)
```
> Note that `map_map` is *deprecated*.
<!--CameLIGO-->
```cameligo group=maps
let map_op (m : register) : register =
let increment = fun (i,j : address * move) -> j.0, j.1 + 1
in Map.map increment m
```
<!--ReasonLIGO-->
```reasonligo group=maps
let map_op = (m : register) : register => {
let increment = ((i,j): (address, move)) => (j[0], j[1] + 1);
Map.map (increment, m);
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Folded Operations over Maps
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.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=maps
function fold_op (const m : register) : int is
block {
function folded (const i : int; const j : address * move) : int is
i + j.1.1
} with Map.fold (folded, m, 5)
```
> Note that `map_fold` is *deprecated*.
<!--CameLIGO-->
```cameligo group=maps
let fold_op (m : register) : register =
let folded = fun (i,j : int * (address * move)) -> i + j.1.1
in Map.fold folded m 5
```
<!--ReasonLIGO-->
```reasonligo group=maps
let fold_op = (m : register) : register => {
let folded = ((i,j): (int, (address, move))) => i + j[1][1];
Map.fold (folded, m, 5);
};
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -1,201 +1,220 @@
--- ---
id: set-reference id: set-reference
title: Set — Unordered unique collection of a type title: Sets — Unordered unique collection of a type
--- ---
## Defining a set 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
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--PascaLIGO-->
```pascaligo group=a ```pascaligo group=sets
type int_set is set (int); const my_set : set (int) = set []
const my_set : int_set = set 1; 2; 3 end
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=a ```cameligo group=sets
type int_set = int set let my_set : int set = Set.empty
let my_set : int_set =
Set.add 3 (Set.add 2 (Set.add 1 (Set.empty: int set)))
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=a ```reasonligo group=sets
type int_set = set (int); let my_set : set (int) = Set.empty;
let my_set : int_set =
Set.add (3, Set.add (2, Set.add (1, Set.empty: set (int))));
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
# Non-empty Sets
## Set.mem(is_member: a', s: a' set) : bool
Check if a set `s` contains the element `is_member`.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--PascaLIGO-->
```pascaligo group=a ```pascaligo group=sets
const contains_three : bool = my_set contains 3 const my_set : set (int) = set [3; 2; 2; 1]
// or alternatively
const contains_three_fn: bool = set_mem (3, my_set);
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=a ```cameligo group=sets
let contains_three: bool = Set.mem 3 my_set let my_set : int set =
``` Set.add 3 (Set.add 2 (Set.add 2 (Set.add 1 (Set.empty : int set))))
<!--ReasonLIGO-->
```reasonligo group=a
let contains_three: bool = Set.mem(3, my_set);
``` ```
<!--ReasonLIGO-->
```reasonligo group=sets
let my_set : set (int) =
Set.add (3, Set.add (2, Set.add (2, Set.add (1, Set.empty : set (int)))));
```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
# Set Membership
## Set.empty() : a' set
Create a new empty set. Needs to be annotated with the set type.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--PascaLIGO-->
```pascaligo group=a ```pascaligo group=sets
const my_set: int_set = set end const contains_3 : bool = my_set contains 3
const my_set_2: int_set = set_empty
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo group=a ```cameligo group=sets
let my_set: int_set = (Set.empty: int set) let contains_3 : bool = Set.mem 3 my_set
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo group=a ```reasonligo group=sets
let my_set: int_set = (Set.empty: set (int)); let contains_3 : bool = Set.mem (3, my_set);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Set.literal(element_list_literal: 'a list) : 'a set # Cardinal of Sets
Create a set from the elements of a list. Note that **you must pass a list literal** The predefined function `Set.size` returns the number of
to this function, a variable will not work. elements in a given set as follows.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=sets
const cardinal : nat = Set.size (my_set)
```
> Note that `size` is *deprecated*.
<!--CameLIGO-->
```cameligo group=sets
let cardinal : nat = Set.size my_set
```
<!--ReasonLIGO-->
```reasonligo group=sets
let cardinal : nat = Set.size (my_set);
```
<!--END_DOCUSAURUS_CODE_TABS-->
# Updating Sets
There are two ways to update a set, that is to add or remove from it.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
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:
```pascaligo group=sets
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.
```pascaligo group=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)
```
<!--CameLIGO-->
```cameligo group=sets
let larger_set : int set = Set.add 4 my_set
let smaller_set : int set = Set.remove 3 my_set
```
<!--ReasonLIGO-->
```reasonligo group=sets
let larger_set : set (int) = Set.add (4, my_set);
let smaller_set : set (int) = Set.remove (3, my_set);
```
<!--END_DOCUSAURUS_CODE_TABS-->
# 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.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=sets
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*.
<!--CameLIGO-->
```cameligo group=sets
let iter_op (s : int set) : unit =
let predicate = fun (i : int) -> assert (i > 3)
in Set.iter predicate s
```
<!--ReasonLIGO-->
```reasonligo group=sets
let iter_op = (s : set (int)) : unit => {
let predicate = (i : int) => assert (i > 3);
Set.iter (predicate, s);
};
```
<!--END_DOCUSAURUS_CODE_TABS-->
## 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.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO--> <!--PascaLIGO-->
```pascaligo ```pascaligo group=sets
const s_fb : set(string) = set [ function sum (const acc : int; const i : int): int is acc + i
"foo" ; const sum_of_elements : int = Set.fold (sum, my_set, 0)
"bar" ; ```
]
> Note that `set_fold` is *deprecated*.
It is possible to use a *loop* over a set as well.
```pascaligo group=sets
function loop (const s : set (int)) : int is block {
var sum : int := 0;
for element in set s block {
sum := sum + element
}
} with sum
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=sets
let literal_op (p: unit) : string set = let sum (acc, i : int * int) : int = acc + i
Set.literal ["foo"; "bar"; "foobar"] let sum_of_elements : int = Set.fold sum my_set 0
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=sets
let literal_op = (p: unit) : set(string) => Set.literal(["foo", "bar", "foobar"]); let sum = ((acc, i) : (int, int)) : int => acc + i;
``` let sum_of_elements : int = Set.fold (sum, my_set, 0);
<!--END_DOCUSAURUS_CODE_TABS-->
## Set.add(addition: a', s: a' set) : a' set
Add the element `addition` to a set `s`.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=a
function add_op (const s : set(string)) : set(string) is
begin skip end with set_add("foobar" , s)
```
<!--CameLIGO-->
```cameligo group=a
type int_set = int set
let my_set : int_set =
Set.add 3 (Set.add 2 (Set.add 1 (Set.empty: int set)))
```
<!--ReasonLIGO-->
```reasonligo group=a
type int_set = set (int);
let my_set : int_set =
Set.add (3, Set.add (2, Set.add (1, Set.empty: set (int))));
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Set.remove(removal: a', s: a' set) : a' set
Remove the element `removal` from a set `s`.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=a
const smaller_set: int_set = set_remove(3, my_set);
```
<!--CameLIGO-->
```cameligo group=a
let smaller_set: int_set = Set.remove 3 my_set
```
<!--ReasonLIGO-->
```reasonligo group=a
let smaller_set: int_set = Set.remove(3, my_set);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Set.fold(folding_function: a' -> a' -> a', s: a' set, initial: a') : a'
Combine the elements of a set into a single value using a folding function.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=a
function sum(const result: int; const i: int): int is result + i;
// Outputs 6
const sum_of_a_set: int = set_fold(sum, my_set, 0);
```
<!--CameLIGO-->
```cameligo group=a
let sum (result, i: int * int) : int = result + i
let sum_of_a_set: int = Set.fold sum my_set 0
```
<!--ReasonLIGO-->
```reasonligo group=a
let sum = (result_i: (int, int)): int => result_i[0] + result_i[1];
let sum_of_a_set: int = Set.fold(sum, my_set, 0);
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
## Set.size(s: a' set) : nat
Get the number of elements in a set.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=a
const set_size: nat = size (my_set)
```
<!--CameLIGO-->
```cameligo group=a
let set_size: nat = Set.size my_set
```
<!--ReasonLIGO-->
```reasonligo group=a
let set_size: nat = Set.size (my_set);
```
<!--END_DOCUSAURUS_CODE_TABS-->