More updates to the documentation. Synced the new reference page.
This commit is contained in:
parent
1522a7d2e4
commit
127a85822f
@ -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,10 +785,10 @@ 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-->
|
||||||
|
|
||||||
|
@ -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`
|
||||||
|
@ -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-->
|
||||||
|
@ -1,137 +1,117 @@
|
|||||||
---
|
---
|
||||||
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-->
|
||||||
const moves: register =
|
```pascaligo group=big_maps
|
||||||
|
const moves : register =
|
||||||
big_map [
|
big_map [
|
||||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
|
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
|
||||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
|
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--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));
|
||||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
|
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--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-->
|
||||||
|
@ -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.
|
||||||
|
|
||||||
@ -11,26 +11,36 @@ 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,110 +251,137 @@ 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-->
|
||||||
|
|
||||||
<!--PascaLIGO-->
|
<!--PascaLIGO-->
|
||||||
```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-->
|
||||||
|
@ -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-->
|
|
||||||
|
@ -1,211 +1,199 @@
|
|||||||
---
|
---
|
||||||
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);
|
||||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
|
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--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));
|
||||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
|
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--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-->
|
||||||
|
@ -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-->
|
|
||||||
|
Loading…
Reference in New Issue
Block a user