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

View File

@ -213,7 +213,7 @@ let c : tez = 5n * 5mutez;
<!--END_DOCUSAURUS_CODE_TABS-->
## Division
## Euclidean Division
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-->
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
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 b : nat = abs (1);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## 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-->
### Adding to Lists
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
*map data structure*) and the *fold operation*.
#### Iterated Operation over Lists
The first, the *iterated operation*, is an iteration over the list
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
that each value inside of a list is within a certain range, and fail
otherwise. The predefined functional iterator implementing the
iterated operation over lists is called `List.iter`.
on the element of a list, or fail.
For example you might want to check that each value inside of a list
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
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
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.
whereas they can be repeated in a *list*.
### Empty Sets
@ -447,6 +447,9 @@ elements in a given set as follows.
```pascaligo group=sets
const cardinal : nat = Set.size (my_set)
```
> Note that `size` is *deprecated*.
<!--CameLIGO-->
```cameligo group=sets
@ -636,12 +639,9 @@ traversal of the data structure is over. The predefined fold over sets
is called `Set.fold`.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=sets
function sum (const acc : int; const i : int): int is acc + i
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 group=sets
let sum (acc, i : int * int) : int = acc + i
let sum_of_elements : int = Set.fold sum my_set 0
```
<!--ReasonLIGO-->
```reasonligo group=sets
let sum = ((acc, i) : (int, int)) : int => acc + i;
let sum_of_elements : int = Set.fold (sum, my_set, 0);
```
<!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -1,137 +1,117 @@
---
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-->
<!--Pascaligo-->
```pascaligo group=big_map
<!--PascaLIGO-->
```pascaligo group=big_maps
type move is int * int
type register is big_map (address, move)
```
<!--CameLIGO-->
```cameligo group=big_map
```cameligo group=big_maps
type move = int * int
type register = (address, move) big_map
```
<!--ReasonLIGO-->
```reasonligo group=big_map
```reasonligo group=big_maps
type move = (int, int);
type register = big_map (address, move);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Creating an Empty Big Map
Create an empty big map.
# Creating an Empty Big Map
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=big_map
```pascaligo group=big_maps
const empty : register = big_map []
```
<!--CameLIGO-->
```cameligo group=big_map
```cameligo group=big_maps
let empty : register = Big_map.empty
```
<!--ReasonLIGO-->
```reasonligo group=big_map
```reasonligo group=big_maps
let empty : register = Big_map.empty
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Populating A Big Map
# Creating a Non-empty Map
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=big_map
const moves: register =
<!--PascaLIGO-->
```pascaligo group=big_maps
const moves : register =
big_map [
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
```
<!--CameLIGO-->
```cameligo group=big_map
let moves: register =
```cameligo group=big_maps
let moves : register =
Big_map.literal [
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2));
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
```
<!--ReasonLIGO-->
```reasonligo group=big_map
let moves: register =
```reasonligo group=big_maps
let moves : register =
Big_map.literal ([
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Retrieving a Value in a Big Map
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.
# Accessing Values
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=big_map
<!--PascaLIGO-->
```pascaligo group=big_maps
const my_balance : option (move) =
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
```
<!--CameLIGO-->
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
```cameligo group=big_maps
let my_balance : move option =
Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves
```
<!--ReasonLIGO-->
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
```reasonligo group=big_maps
let my_balance : option (move) =
Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves);
```
<!--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
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*.
# Updating Big Maps
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
The values of a PascaLIGO big map can be updated using the ordinary
assignment syntax:
```pascaligo group=big_map
<!--PascaLIGO-->
```pascaligo group=big_maps
function add (var m : register) : register is
block {
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9)
@ -140,114 +120,45 @@ function add (var m : register) : register is
const updated_map : register = add (moves)
```
See further for the removal of bindings.
<!--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
<!--CameLIGO-->
```cameligo group=big_maps
let updated_map : register =
Big_map.update
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (Some (4,9)) moves
```
<!--Reasonligo-->
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
<!--ReasonLIGO-->
```reasonligo group=big_maps
let updated_map : register =
Big_map.update
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Adding a Binding to a Big Map
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.
# Removing Bindings
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=big_map
function delete (const key : address; var moves : register) : register is
```pascaligo group=big_maps
function rem (var m : register) : register is
block {
remove key from map moves
} with moves
remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) from map moves
} with m
const updated_map : register = rem (moves)
```
<!--CameLIGO-->
In CameLIGO, we use the predefined function `Big_map.remove` whose
type is `'key -> ('key, 'value) big_map -> ('key, 'value)
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
```cameligo group=big_maps
let updated_map : register =
Map.remove ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
```
<!--ReasonLIGO-->
In ReasonLIGO, we use the predefined function `Big_map.remove` whose
type is `('key, ('key, 'value) big_map) : ('key, 'value)
big_map`. Here is an example:
```reasonligo group=big_map
let delete = ((key, moves) : (address, register)) : register =>
Map.remove (key, moves);
```reasonligo group=big_maps
let updated_map : register =
Map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves)
```
<!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -1,9 +1,9 @@
---
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.
@ -11,26 +11,36 @@ Get the balance for the contract.
<!--PascaLIGO-->
```pascaligo
function main (const p : unit; const s: tez) : list(operation) * tez is
((nil : list(operation)), balance)
function main (const p : unit; const s: tez) : list (operation) * tez is
((nil : list (operation)), Tezos.balance)
```
> Note that `balance` and `Current.balance` are *deprecated*.
<!--CameLIGO-->
```cameligo
let main (p, s : unit * tez) =
([] : operation list), balance
let main (p,s : unit * tez) = ([] : operation list), Tezos.balance
```
> Note that `balance` and `Current.balance` are *deprecated*.
<!--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-->
## 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
@ -38,118 +48,134 @@ In LIGO, timestamps are type compatible in operations with `int`(s). This lets y
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=b
const today: timestamp = now;
const one_day: int = 86400;
const today: timestamp = Tezos.now;
const one_day: int = 86_400;
const in_24_hrs: timestamp = today + one_day;
const some_date: timestamp = ("2000-01-01T10:10:10Z" : timestamp);
const one_day_later: timestamp = some_date + one_day;
```
> Note that `now` is *deprecated*.
<!--CameLIGO-->
```cameligo group=b
let today: timestamp = Current.time
let one_day: int = 86400
let today: timestamp = Tezos.now
let one_day: int = 86_400
let in_24_hrs: timestamp = today + one_day
let some_date: timestamp = ("2000-01-01t10:10:10Z" : timestamp)
let one_day_later: timestamp = some_date + one_day
```
> Note that `Current.time` is *deprecated*.
<!--ReasonLIGO-->
```reasonligo group=b
let today: timestamp = Current.time;
let one_day: int = 86400;
let today: timestamp = Tezos.now;
let one_day: int = 86_400;
let in_24_hrs: timestamp = today + one_day;
let some_date: timestamp = ("2000-01-01t10:10:10Z" : timestamp);
let one_day_later: timestamp = some_date + one_day;
```
> Note that `Current.time` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS-->
#### 24 hours ago
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=c
const today: timestamp = now;
const one_day: int = 86400;
const today: timestamp = Tezos.now;
const one_day: int = 86_400;
const in_24_hrs: timestamp = today - one_day;
```
> Note that `now` is *deprecated*.
<!--CameLIGO-->
```cameligo group=c
let today: timestamp = Current.time
let one_day: int = 86400
let today: timestamp = Tezos.now
let one_day: int = 86_400
let in_24_hrs: timestamp = today - one_day
```
> Note that `Current.time` is *deprecated*.
<!--ReasonLIGO-->
```reasonligo group=c
let today: timestamp = Current.time;
let one_day: int = 86400;
let today: timestamp = Tezos.now;
let one_day: int = 86_400;
let in_24_hrs: timestamp = today - one_day;
```
> Note that `Current.time` is *deprecated*.
<!--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-->
<!--Pascaligo-->
```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 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 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-->
## 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-->
<!--PascaLIGO-->
```pascaligo
function check (const p: unit) : int is
begin
var result : int := 0;
if amount = 100tz then
result := 42
else
result := 0
end with result
function threshold (const p : unit) : int is
if Tezos.amount = 100tz then 42 else 0
```
> Note that `amount` is *deprecated*.
<!--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
let check_ = (p: unit) : int =>
if (Current.amount == 100tz) {
42;
}
else {
0;
};
let threshold = (p : unit) : int =>
if (Tezos.amount == 100tz) { 42; } else { 0; };
```
> Note that `Current.amount` is *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS-->
## Current.sender() : address
## Sender
Get the address that initiated the current transaction.
@ -157,52 +183,67 @@ Get the address that initiated the current transaction.
<!--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
let main (p: unit) : address = Current.sender
let main (p: unit) : address = Tezos.sender
```
> Note that `Current.sender` is *deprecated*.
<!--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-->
## 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-->
<!--PascaLIGO-->
```pascaligo
function main (const p : key_hash) : address is block {
const c : contract(unit) = implicit_account(p) ;
} with address(c)
const c : contract (unit) = Tezos.implicit_account (p)
} with Tezos.address(c)
```
> Note that `implicit_account` and `address` are *deprecated*.
<!--CameLIGO-->
```cameligo
let main (p : key_hash) =
let c : unit contract = Current.implicit_account p in
Current.address c
let c : unit contract = Tezos.implicit_account p
in Tezos.address c
```
> Note that `Current.implicit_account` and `Current.address` are
> *deprecated*.
<!--ReasonLIGO-->
```reasonligo
let main = (p : key_hash) : address => {
let c : contract(unit) = Current.implicit_account(p) ;
Current.address(c) ;
let c : contract (unit) = Tezos.implicit_account (p);
Tezos.address (c);
};
```
> Note that `Current.implicit_account` and `Current.address` are
> *deprecated*.
<!--END_DOCUSAURUS_CODE_TABS-->
## Current.self_address() : address
## Self Address
Get the address of the currently running contract.
@ -210,110 +251,137 @@ Get the address of the currently running contract.
<!--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
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
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-->
## Current.implicit_account(p: key_hash) : a' contract
## Implicit Account
Get the default contract associated with an on-chain keypair. This contract
doesn't execute code, instead it exists to receive money on behalf of a keys
owner.
Get the default contract associated with an on-chain key-pair. This
contract does not execute code, instead it exists to receive tokens on
behalf of a key's owner.
<!--DOCUSAURUS_CODE_TABS-->
<!--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
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
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-->
## Current.source() : address
## Source
Get the _originator_ of the current transaction. That is, if a chain of transactions
led to the current execution get the address that began the chain. Not to be confused
with `Current.sender`, which gives the address of the contract or user which directly
caused the current transaction.
Get the _originator_ (address) of the current transaction. That is, if
a chain of transactions led to the current execution get the address
that began the chain. Not to be confused with `Tezos.sender`, which
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 `SOURCE` over `SENDER`:
> ⚠️ There are a few caveats you should keep in mind before using
> `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
> 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.
> 1. `Tezos.source` will never be a contract, so if you want to allow
> 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-->
<!--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
let main (p: unit) : address = Current.source
let main (p : unit) : address = Tezos.source
```
> Note that `Current.source` is *deprecated*.
<!--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-->
## Current.failwith(error_message: string) : a'
## Failwith
Cause the contract to fail with an error message.
> ⚠ Using this currently requires a type annotation on the failwith to unify it
> with the type of whatever other code branch it's on.
> ⚠ Using this currently requires in general a type annotation on the
> `failwith` call.
<!--DOCUSAURUS_CODE_TABS-->
<!--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 {
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
let main (p,s: unit * unit) =
if true then failwith "This contract always fails" else ()
let main (p,s : int * unit) = if p > 10 then failwith "Failure."
```
<!--ReasonLIGO-->
```reasonligo
let main = ((p,s): (unit, unit)) =>
if (true) {
failwith("This contract always fails");
} else {
();
};
let main = ((p,s) : (int, unit)) =>
if (p > 10) { failwith ("Failure."); };
```
<!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -1,6 +1,6 @@
---
id: list-reference
title: List — Linear Collections
title: Lists — Linear Collections
---
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
think of a list a *stack*, where the top is written on the left.
## Defining Lists
# Defining Lists
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
@ -34,7 +34,7 @@ let my_list : list (int) = [1, 2, 2]; // The head is 1
<!--END_DOCUSAURUS_CODE_TABS-->
### Adding to Lists
# Adding to Lists
Lists can be augmented by adding an element before the head (or, in
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-->
### Functional Iteration over Lists
# Functional Iteration over Lists
A *functional iterator* is a function that traverses a data 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
*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
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
block {
function iterated (const i : int) : unit is
if i > 2 then Unit else (failwith ("Below range.") : unit)
} with list_iter (iterated, l)
if i > 3 then Unit else (failwith ("Below range.") : unit)
} with List.iter (iterated, l)
```
> Note that `list_iter` is *deprecated*.
<!--CameLIGO-->
```cameligo group=lists
@ -108,7 +112,7 @@ let iter_op = (l : list (int)) : unit => {
<!--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
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
// 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 group=lists
@ -144,7 +150,8 @@ let plus_one : list (int) = List.map (increment, larger_list);
```
<!--END_DOCUSAURUS_CODE_TABS-->
#### Folded Operation over Lists
## Folded Operation over Lists
A *folded operation* is the most general of iterations. The folded
function takes two arguments: an *accumulator* and the structure
@ -158,9 +165,11 @@ traversal of the data structure is over.
```pascaligo group=lists
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 group=lists
@ -176,7 +185,7 @@ let sum_of_elements : int = List.fold (sum, my_list, 0);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## List Length
# List Length
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)
```
> Note that `size` is *deprecated*.
<!--CameLIGO-->
```cameligo
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-->
## 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,211 +1,199 @@
---
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-->
<!--Pascaligo-->
```pascaligo group=map
<!--PascaLIGO-->
```pascaligo group=maps
type move is int * int
type register is map (address, move)
```
<!--CameLIGO-->
```cameligo group=map
```cameligo group=maps
type move = int * int
type register = (address, move) map
```
<!--ReasonLIGO-->
```reasonligo group=map
```reasonligo group=maps
type move = (int, int);
type register = map (address, move);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Creating an Empty Map
Create an empty map.
# Creating an Empty Map
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=map
```pascaligo group=maps
const empty : register = map []
```
<!--CameLIGO-->
```cameligo group=map
```cameligo group=maps
let empty : register = Map.empty
```
<!--ReasonLIGO-->
```reasonligo group=map
```reasonligo group=maps
let empty : register = Map.empty
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Populating A Map
# Creating a Non-empty Map
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=map
const moves: register =
<!--PascaLIGO-->
```pascaligo group=maps
const moves : register =
map [
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address) -> (1,2);
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) -> (0,3)]
```
<!--CameLIGO-->
```cameligo group=map
let moves: register =
```cameligo group=maps
let moves : register =
Map.literal [
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), (1,2));
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (0,3))]
```
<!--ReasonLIGO-->
```reasonligo group=map
let moves: register =
```reasonligo group=maps
let moves : register =
Map.literal ([
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Retrieving a Value in a Map
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.
# Accessing Map Bindings
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=map
<!--PascaLIGO-->
```pascaligo group=maps
const my_balance : option (move) =
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
```
<!--CameLIGO-->
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
```cameligo group=maps
let my_balance : move option =
Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) moves
```
<!--ReasonLIGO-->
The function is `Map.find_opt` whose type is `('key, ('key,
'value) map) : 'value option`. Here is an example:
```reasonligo group=map
```reasonligo group=maps
let my_balance : option (move) =
Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves);
Map.find_opt (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), moves);
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Updating a Binding in 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. We
may even want to retain the key but not the associated value. All
those operations are called *updates*.
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
*pattern matching*.
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
The values of a PascaLIGO map can be updated using the ordinary
assignment syntax:
```pascaligo group=map
function add (var m : register) : register is
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)
<!--PascaLIGO-->
```pascaligo group=maps
function force_access (const key : address; const moves : register) : move is
case moves[key] of
Some (move) -> move
| None -> (failwith ("No move.") : move)
end
```
<!--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
is `'key -> 'value -> ('key, 'value) map -> ('key, 'value)
map`. Recall that the function `Map.add` must always be fully
applied to its arguments. Here is an example:
<!--ReasonLIGO-->
```reasonligo group=maps
let force_access = ((key, moves) : (address, register)) : move => {
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 =
Map.add
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address) (4,9) m
```
<!--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
type is `('key, 'value, ('key, 'value) map : ('key, 'value)
map`. Here is an example:
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.
```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 =>
Map.add
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m);
@ -213,14 +201,12 @@ let add = (m : register) : register =>
<!--END_DOCUSAURUS_CODE_TABS-->
## Removing a Binding from a Map
Remove a key and its associated value from the map.
To remove a binding from a map, we need its key.
<!--DOCUSAURUS_CODE_TABS-->
<!--PascaLIGO-->
```pascaligo group=map
```pascaligo group=maps
function delete (const key : address; var moves : register) : register is
block {
remove key from map moves
@ -228,47 +214,144 @@ function delete (const key : address; var moves : register) : register is
```
<!--CameLIGO-->
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
```cameligo group=maps
let delete (key, moves : address * register) : register =
Map.remove key moves
```
<!--ReasonLIGO-->
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
```reasonligo group=maps
let delete = ((key, moves) : (address, register)) : register =>
Map.remove (key, moves);
```
<!--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-->
<!--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 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 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-->

View File

@ -1,201 +1,220 @@
---
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-->
<!--Pascaligo-->
```pascaligo group=a
type int_set is set (int);
const my_set : int_set = set 1; 2; 3 end
<!--PascaLIGO-->
```pascaligo group=sets
const my_set : set (int) = set []
```
<!--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)))
```cameligo group=sets
let my_set : int set = Set.empty
```
<!--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))));
```reasonligo group=sets
let my_set : set (int) = Set.empty;
```
<!--END_DOCUSAURUS_CODE_TABS-->
## Set.mem(is_member: a', s: a' set) : bool
Check if a set `s` contains the element `is_member`.
# Non-empty Sets
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=a
const contains_three : bool = my_set contains 3
// or alternatively
const contains_three_fn: bool = set_mem (3, my_set);
<!--PascaLIGO-->
```pascaligo group=sets
const my_set : set (int) = set [3; 2; 2; 1]
```
<!--CameLIGO-->
```cameligo group=a
let contains_three: bool = Set.mem 3 my_set
```
<!--ReasonLIGO-->
```reasonligo group=a
let contains_three: bool = Set.mem(3, my_set);
```cameligo group=sets
let my_set : int set =
Set.add 3 (Set.add 2 (Set.add 2 (Set.add 1 (Set.empty : int 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-->
## Set.empty() : a' set
Create a new empty set. Needs to be annotated with the set type.
# Set Membership
<!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo-->
```pascaligo group=a
const my_set: int_set = set end
const my_set_2: int_set = set_empty
<!--PascaLIGO-->
```pascaligo group=sets
const contains_3 : bool = my_set contains 3
```
<!--CameLIGO-->
```cameligo group=a
let my_set: int_set = (Set.empty: int set)
```cameligo group=sets
let contains_3 : bool = Set.mem 3 my_set
```
<!--ReasonLIGO-->
```reasonligo group=a
let my_set: int_set = (Set.empty: set (int));
```reasonligo group=sets
let contains_3 : bool = Set.mem (3, my_set);
```
<!--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**
to this function, a variable will not work.
The predefined function `Set.size` returns the number of
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-->
<!--PascaLIGO-->
```pascaligo
const s_fb : set(string) = set [
"foo" ;
"bar" ;
]
```pascaligo group=sets
function sum (const acc : int; const i : int): int is acc + i
const sum_of_elements : int = Set.fold (sum, my_set, 0)
```
> Note that `set_fold` is *deprecated*.
It is possible to use a *loop* over a set as well.
```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
let literal_op (p: unit) : string set =
Set.literal ["foo"; "bar"; "foobar"]
```cameligo group=sets
let sum (acc, i : int * int) : int = acc + i
let sum_of_elements : int = Set.fold sum my_set 0
```
<!--ReasonLIGO-->
```reasonligo
let literal_op = (p: unit) : set(string) => Set.literal(["foo", "bar", "foobar"]);
```
<!--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);
```reasonligo group=sets
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.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-->