Updates.
This commit is contained in:
parent
334deea8ec
commit
729575af11
@ -15,10 +15,10 @@ Each `block` needs to include at least one `instruction`, or a *placeholder* ins
|
||||
|
||||
```pascaligo skip
|
||||
// shorthand syntax
|
||||
block { skip }
|
||||
block { a := a + 1 }
|
||||
// verbose syntax
|
||||
begin
|
||||
skip
|
||||
a := a + 1
|
||||
end
|
||||
```
|
||||
|
||||
@ -29,16 +29,17 @@ end
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
|
||||
Functions in PascaLIGO are defined using the `function` keyword followed by their `name`, `parameters` and `return` type definitions.
|
||||
|
||||
Here's how you define a basic function that accepts two `ints` and returns a single `int`:
|
||||
Functions in PascaLIGO are defined using the `function` keyword
|
||||
followed by their `name`, `parameters` and `return` type definitions.
|
||||
|
||||
Here's how you define a basic function that accepts two `int`s and
|
||||
returns a single `int`:
|
||||
|
||||
```pascaligo group=a
|
||||
function add(const a: int; const b: int): int is
|
||||
begin
|
||||
const result: int = a + b;
|
||||
end with result;
|
||||
function add(const a: int; const b: int): int is
|
||||
begin
|
||||
const result: int = a + b;
|
||||
end with result;
|
||||
```
|
||||
|
||||
The function body consists of two parts:
|
||||
@ -48,8 +49,10 @@ The function body consists of two parts:
|
||||
|
||||
#### Blockless functions
|
||||
|
||||
Functions that can contain all of their logic into a single instruction/expression, can be defined without the surrounding `block`.
|
||||
Instead, you can inline the necessary logic directly, like this:
|
||||
Functions that can contain all of their logic into a single
|
||||
instruction/expression, can be defined without the surrounding
|
||||
`block`. Instead, you can inline the necessary logic directly, like
|
||||
this:
|
||||
|
||||
```pascaligo group=b
|
||||
function add(const a: int; const b: int): int is a + b
|
||||
@ -57,72 +60,78 @@ function add(const a: int; const b: int): int is a + b
|
||||
|
||||
<!--CameLIGO-->
|
||||
|
||||
Functions in CameLIGO are defined using the `let` keyword, like value bindings.
|
||||
The difference is that after the value name a list of function parameters is provided,
|
||||
along with a return type.
|
||||
Functions in CameLIGO are defined using the `let` keyword, like value
|
||||
bindings. The difference is that after the value name a list of
|
||||
function parameters is provided, along with a return type.
|
||||
|
||||
CameLIGO is a little different from other syntaxes when it comes to function
|
||||
parameters. In OCaml, functions can only take one parameter. To get functions
|
||||
with multiple arguments like we're used to in traditional programming languages,
|
||||
a technique called [currying](https://en.wikipedia.org/wiki/Currying) is used.
|
||||
Currying essentially translates a function with multiple arguments into a series
|
||||
of single argument functions, each returning a new function accepting the next
|
||||
argument until every parameter is filled. This is useful because it means that
|
||||
CameLIGO can support [partial application](https://en.wikipedia.org/wiki/Partial_application).
|
||||
CameLIGO is a little different from other syntaxes when it comes to
|
||||
function parameters. In OCaml, functions can only take one
|
||||
parameter. To get functions with multiple arguments like we are used
|
||||
to in traditional programming languages, a technique called
|
||||
[currying](https://en.wikipedia.org/wiki/Currying) is used. Currying
|
||||
essentially translates a function with multiple arguments into a
|
||||
series of single argument functions, each returning a new function
|
||||
accepting the next argument until every parameter is filled. This is
|
||||
useful because it means that CameLIGO can support
|
||||
[partial application](https://en.wikipedia.org/wiki/Partial_application).
|
||||
|
||||
Currying is however *not* the preferred way to pass function arguments in CameLIGO.
|
||||
While this approach is faithful to the original OCaml, it's costlier in Michelson
|
||||
than naive function execution accepting multiple arguments. Instead for most
|
||||
functions with more than one parameter we should place the arguments in a
|
||||
[tuple](language-basics/sets-lists-tuples.md) and pass the tuple in as a single
|
||||
parameter.
|
||||
Currying is however *not* the preferred way to pass function arguments
|
||||
in CameLIGO. While this approach is faithful to the original OCaml,
|
||||
it's costlier in Michelson than naive function execution accepting
|
||||
multiple arguments. Instead for most functions with more than one
|
||||
parameter we should place the arguments in a
|
||||
[tuple](language-basics/sets-lists-tuples.md) and pass the tuple in as
|
||||
a single parameter.
|
||||
|
||||
Here's how you define a basic function that accepts two `ints` and returns an `int` as well:
|
||||
Here is how you define a basic function that accepts two `ints` and
|
||||
returns an `int` as well:
|
||||
|
||||
```cameligo group=b
|
||||
|
||||
let add (a,b: int * int) : int = a + b
|
||||
|
||||
let add_curry (a: int) (b: int) : int = a + b
|
||||
```
|
||||
|
||||
The function body is a series of expressions, which are evaluated to give the return
|
||||
value.
|
||||
|
||||
The function body is a series of expressions, which are evaluated to
|
||||
give the return value.
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
|
||||
Functions in ReasonLIGO are defined using the `let` keyword, like value bindings.
|
||||
The difference is that after the value name a list of function parameters is provided,
|
||||
along with a return type.
|
||||
Functions in ReasonLIGO are defined using the `let` keyword, like
|
||||
value bindings. The difference is that after the value name a list of
|
||||
function parameters is provided, along with a return type.
|
||||
|
||||
Here's how you define a basic function that accepts two `ints` and returns an `int` as well:
|
||||
Here is how you define a basic function that accepts two `int`s and
|
||||
returns an `int` as well:
|
||||
|
||||
```reasonligo group=b
|
||||
let add = ((a,b): (int, int)) : int => a + b;
|
||||
```
|
||||
|
||||
The function body is a series of expressions, which are evaluated to give the return
|
||||
value.
|
||||
The function body is a series of expressions, which are evaluated to
|
||||
give the return value.
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
## Anonymous functions
|
||||
|
||||
Functions without a name, also known as anonymous functions are useful in cases when you want to pass the function as an argument or assign it to a key in a record/map.
|
||||
Functions without a name, also known as anonymous functions are useful
|
||||
in cases when you want to pass the function as an argument or assign
|
||||
it to a key in a record or a map.
|
||||
|
||||
Here's how to define an anonymous function assigned to a variable `increment`, with it's appropriate function type signature.
|
||||
Here's how to define an anonymous function assigned to a variable
|
||||
`increment`, with it is appropriate function type signature.
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo group=c
|
||||
const increment : (int -> int) = (function (const i : int) : int is i + 1);
|
||||
const increment : int -> int = function (const i : int) : int is i + 1;
|
||||
// a = 2
|
||||
const a: int = increment(1);
|
||||
const a: int = increment (1);
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo group=c
|
||||
let increment : (int -> int) = fun (i: int) -> i + 1
|
||||
let increment : int -> int = fun (i: int) -> i + 1
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
|
@ -3,19 +3,22 @@ id: maps-records
|
||||
title: Maps, Records
|
||||
---
|
||||
|
||||
So far we've seen pretty basic data types. LIGO also offers more complex built-in constructs, such as Maps and Records.
|
||||
So far we have seen pretty basic data types. LIGO also offers more
|
||||
complex built-in constructs, such as maps and records.
|
||||
|
||||
## Maps
|
||||
|
||||
Maps are natively available in Michelson, and LIGO builds on top of them. A requirement for a Map is that its keys be of the same type, and that type must be comparable.
|
||||
Maps are natively available in Michelson, and LIGO builds on top of
|
||||
them. A requirement for a map is that its keys be of the same type,
|
||||
and that type must be comparable.
|
||||
|
||||
Here's how a custom map type is defined:
|
||||
Here is how a custom map type is defined:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
type move is (int * int);
|
||||
type moveset is map(address, move);
|
||||
type move is int * int
|
||||
type moveset is map(address, move)
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
@ -32,7 +35,7 @@ type moveset = map(address, move);
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
And here's how a map value is populated:
|
||||
And here is how a map value is populated:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
@ -77,7 +80,10 @@ let moves : moveset =
|
||||
|
||||
### Accessing map values by key
|
||||
|
||||
If we want to access a move from our moveset above, we can use the `[]` operator/accessor to read the associated `move` value. However, the value we'll get will be wrapped as an optional; in our case `option(move)`. Here's an example:
|
||||
If we want to access a move from our moveset above, we can use the
|
||||
`[]` operator/accessor to read the associated `move` value. However,
|
||||
the value we will get will be wrapped as an optional; in our case
|
||||
`option(move)`. Here is an example:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
@ -175,8 +181,8 @@ otherwise.
|
||||
function iter_op (const m : moveset) : unit is
|
||||
block {
|
||||
function aggregate (const i : address ; const j : move) : unit is block
|
||||
{ if (j.1 > 1) then skip else failwith("fail") } with unit ;
|
||||
} with map_iter(aggregate, m) ;
|
||||
{ if j.1 > 1 then skip else failwith("fail") } with unit
|
||||
} with map_iter(aggregate, m);
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
@ -189,7 +195,7 @@ let iter_op (m : moveset) : unit =
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
let iter_op = (m: moveset): unit => {
|
||||
let assert_eq = ((i,j): (address, move)) => assert(j[0] > 1);
|
||||
let assert_eq = ((i,j): (address, move)) => assert (j[0] > 1);
|
||||
Map.iter(assert_eq, m);
|
||||
};
|
||||
```
|
||||
@ -202,8 +208,8 @@ let iter_op = (m: moveset): unit => {
|
||||
```pascaligo
|
||||
function map_op (const m : moveset) : moveset is
|
||||
block {
|
||||
function increment (const i : address ; const j : move) : move is block { skip } with (j.0, j.1 + 1) ;
|
||||
} with map_map(increment, m) ;
|
||||
function increment (const i : address ; const j : move) : move is (j.0, j.1 + 1);
|
||||
} with map_map (increment, m);
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
@ -222,29 +228,30 @@ let map_op = (m: moveset): moveset => {
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
`fold` is an aggregation function that return the combination of a maps contents.
|
||||
`fold` is an aggregation function that return the combination of a
|
||||
maps contents.
|
||||
|
||||
The fold is a loop which extracts an element of the map on each iteration. It then
|
||||
provides this element and an existing value to a folding function which combines them.
|
||||
On the first iteration, the existing value is an initial expression given by the
|
||||
programmer. On each subsequent iteration it is the result of the previous iteration.
|
||||
The fold is a loop which extracts an element of the map on each
|
||||
iteration. It then provides this element and an existing value to a
|
||||
folding function which combines them. On the first iteration, the
|
||||
existing value is an initial expression given by the programmer. On
|
||||
each subsequent iteration it is the result of the previous iteration.
|
||||
It eventually returns the result of combining all the elements.
|
||||
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
function fold_op (const m : moveset) : int is
|
||||
block {
|
||||
function aggregate (const j : int ; const cur : (address * (int * int))) : int is j + cur.1.1 ;
|
||||
} with map_fold(aggregate, m , 5)
|
||||
function aggregate (const j : int; const cur : address * (int * int)) : int is j + cur.1.1
|
||||
} with map_fold(aggregate, m, 5)
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
let fold_op (m : moveset) : moveset =
|
||||
let aggregate = fun (i,j: int * (address * (int * int))) -> i + j.1.1 in
|
||||
Map.fold aggregate m 5
|
||||
let aggregate = fun (i,j: int * (address * (int * int))) -> i + j.1.1
|
||||
in Map.fold aggregate m 5
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
@ -268,13 +275,13 @@ too expensive were it not for big maps. Big maps are a data structure offered by
|
||||
Tezos which handles the scaling concerns for us. In LIGO, the interface for big
|
||||
maps is analogous to the one used for ordinary maps.
|
||||
|
||||
Here's how we define a big map:
|
||||
Here is how we define a big map:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
type move is (int * int);
|
||||
type moveset is big_map(address, move);
|
||||
type move is (int * int)
|
||||
type moveset is big_map (address, move)
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
@ -291,16 +298,17 @@ type moveset = big_map(address, move);
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
And here's how a map value is populated:
|
||||
And here is how a map value is populated:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
|
||||
```pascaligo
|
||||
const moves: moveset = big_map
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1, 2);
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0, 3);
|
||||
end
|
||||
const moves: moveset =
|
||||
big_map
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1,2);
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0,3);
|
||||
end
|
||||
```
|
||||
> Notice the `->` between the key and its value and `;` to separate individual map entries.
|
||||
>
|
||||
@ -309,45 +317,51 @@ end
|
||||
<!--CameLIGO-->
|
||||
|
||||
```cameligo
|
||||
let moves: moveset = Big_map.literal
|
||||
[ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1, 2)) ;
|
||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0, 3)) ;
|
||||
let moves: moveset =
|
||||
Big_map.literal [
|
||||
(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1,2));
|
||||
(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0,3));
|
||||
]
|
||||
```
|
||||
> Big_map.literal constructs the map from a list of key-value pair tuples, `(<key>, <value>)`.
|
||||
> Note also the `;` to separate individual map entries.
|
||||
>
|
||||
> `("<string value>": address)` means that we type-cast a string into an address.
|
||||
> `("<string value>": address)` means that we cast a string into an address.
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
|
||||
```reasonligo
|
||||
let moves: moveset =
|
||||
Big_map.literal([
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1, 2)),
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0, 3)),
|
||||
Big_map.literal ([
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1,2)),
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0,3)),
|
||||
]);
|
||||
```
|
||||
> Big_map.literal constructs the map from a list of key-value pair tuples, `(<key>, <value>)`.
|
||||
>
|
||||
> `("<string value>": address)` means that we type-cast a string into an address.
|
||||
> `("<string value>": address)` means that we cast a string into an address.
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
### Accessing map values by key
|
||||
|
||||
If we want to access a move from our moveset above, we can use the `[]` operator/accessor to read the associated `move` value. However, the value we'll get will be wrapped as an optional; in our case `option(move)`. Here's an example:
|
||||
If we want to access a move from our moveset above, we can use the
|
||||
`[]` operator/accessor to read the associated `move` value. However,
|
||||
the value we will get will be wrapped as an optional; in our case
|
||||
`option(move)`. Here is an example:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
const my_balance : option(move) = moves[("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)];
|
||||
const my_balance : option(move) =
|
||||
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)]
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
|
||||
```cameligo
|
||||
let my_balance : move option = Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
|
||||
let my_balance : move option =
|
||||
Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
@ -360,24 +374,28 @@ let my_balance : option(move) =
|
||||
|
||||
#### Obtaining a map value forcefully
|
||||
|
||||
Accessing a value in a map yields an option, however you can also get the value directly:
|
||||
Accessing a value in a map yields an option, however you can also get
|
||||
the value directly:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
const my_balance : move = get_force(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves);
|
||||
const my_balance : move =
|
||||
get_force (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves);
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
|
||||
```cameligo
|
||||
let my_balance : move = Big_map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
|
||||
let my_balance : move =
|
||||
Big_map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
|
||||
```reasonligo
|
||||
let my_balance : move = Big_map.find("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves);
|
||||
let my_balance : move =
|
||||
Big_map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves);
|
||||
```
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
@ -388,19 +406,21 @@ let my_balance : move = Big_map.find("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": add
|
||||
|
||||
<!--Pascaligo-->
|
||||
|
||||
The values of a PascaLIGO big map can be updated using the ordinary assignment syntax:
|
||||
The values of a PascaLIGO big map can be updated using the ordinary
|
||||
assignment syntax:
|
||||
|
||||
```pascaligo
|
||||
|
||||
function set_ (var m : moveset) : moveset is
|
||||
block {
|
||||
m[("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9);
|
||||
m [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9);
|
||||
} with m
|
||||
```
|
||||
|
||||
<!--Cameligo-->
|
||||
|
||||
We can update a big map in CameLIGO using the `Big_map.update` built-in:
|
||||
We can update a big map in CameLIGO using the `Big_map.update`
|
||||
built-in:
|
||||
|
||||
```cameligo
|
||||
|
||||
@ -410,10 +430,11 @@ let updated_map : moveset =
|
||||
|
||||
<!--Reasonligo-->
|
||||
|
||||
We can update a big map in ReasonLIGO using the `Big_map.update` built-in:
|
||||
We can update a big map in ReasonLIGO using the `Big_map.update`
|
||||
built-in:
|
||||
|
||||
```reasonligo
|
||||
let updated_map: moveset =
|
||||
let updated_map : moveset =
|
||||
Big_map.update(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some((4,9)), moves);
|
||||
```
|
||||
|
||||
@ -421,75 +442,79 @@ let updated_map: moveset =
|
||||
|
||||
## Records
|
||||
|
||||
Records are a construct introduced in LIGO, and are not natively available in Michelson. The LIGO compiler translates records into Michelson `Pairs`.
|
||||
Records are a construct introduced in LIGO, and are not natively
|
||||
available in Michelson. The LIGO compiler translates records into
|
||||
Michelson `Pairs`.
|
||||
|
||||
Here's how a custom record type is defined:
|
||||
Here is how a custom record type is defined:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
type user is record
|
||||
id: nat;
|
||||
is_admin: bool;
|
||||
name: string;
|
||||
end
|
||||
type user is
|
||||
record
|
||||
id : nat;
|
||||
is_admin : bool;
|
||||
name : string
|
||||
end
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
type user = {
|
||||
id: nat;
|
||||
is_admin: bool;
|
||||
name: string;
|
||||
id : nat;
|
||||
is_admin : bool;
|
||||
name : string
|
||||
}
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
type user = {
|
||||
id: nat,
|
||||
is_admin: bool,
|
||||
name: string
|
||||
id : nat,
|
||||
is_admin : bool,
|
||||
name : string
|
||||
};
|
||||
```
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
And here's how a record value is populated:
|
||||
And here is how a record value is populated:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo
|
||||
const user: user = record
|
||||
id = 1n;
|
||||
const user : user =
|
||||
record
|
||||
id = 1n;
|
||||
is_admin = True;
|
||||
name = "Alice";
|
||||
end
|
||||
name = "Alice"
|
||||
end
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo
|
||||
let user: user = {
|
||||
id = 1n;
|
||||
let user : user = {
|
||||
id = 1n;
|
||||
is_admin = true;
|
||||
name = "Alice";
|
||||
name = "Alice"
|
||||
}
|
||||
```
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo
|
||||
let user: user = {
|
||||
id: 1n,
|
||||
is_admin: true,
|
||||
name: "Alice"
|
||||
let user : user = {
|
||||
id : 1n,
|
||||
is_admin : true,
|
||||
name : "Alice"
|
||||
};
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
|
||||
### Accessing record keys by name
|
||||
|
||||
If we want to obtain a value from a record for a given key, we can do the following:
|
||||
If we want to obtain a value from a record for a given key, we can do
|
||||
the following:
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
@ -506,5 +531,4 @@ let is_admin : bool = user.is_admin
|
||||
```reasonligo
|
||||
let is_admin: bool = user.is_admin;
|
||||
```
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
@ -3,39 +3,37 @@ id: sets-lists-tuples
|
||||
title: Sets, Lists, Tuples
|
||||
---
|
||||
|
||||
Apart from complex data types such as `maps` and `records`, ligo also exposes `sets`, `lists` and `tuples`.
|
||||
Apart from complex data types such as `maps` and `records`, ligo also
|
||||
exposes `sets`, `lists` and `tuples`.
|
||||
|
||||
> ⚠️ Make sure to pick the appropriate data type for your use case; it carries not only semantic but also gas related costs.
|
||||
|
||||
## Sets
|
||||
|
||||
Sets are similar to lists. The main difference is that elements of a `set` must be *unique*.
|
||||
Sets are similar to lists. The main difference is that elements of a
|
||||
`set` must be *unique*.
|
||||
|
||||
### Defining a set
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo group=a
|
||||
type int_set is set(int);
|
||||
const my_set: int_set = set
|
||||
1;
|
||||
2;
|
||||
3;
|
||||
end
|
||||
type int_set is set (int);
|
||||
const my_set : int_set = set 1; 2; 3 end
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
```cameligo group=a
|
||||
type int_set = int set
|
||||
let my_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))));
|
||||
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-->
|
||||
@ -45,8 +43,8 @@ let my_set: int_set =
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo group=a
|
||||
const my_set: int_set = set end;
|
||||
const my_set_2: int_set = set_empty;
|
||||
const my_set: int_set = set end
|
||||
const my_set_2: int_set = set_empty
|
||||
```
|
||||
<!--CameLIGO-->
|
||||
```cameligo group=a
|
||||
@ -54,7 +52,7 @@ let my_set: int_set = (Set.empty: int set)
|
||||
```
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo group=a
|
||||
let my_set: int_set = (Set.empty: set(int));
|
||||
let my_set: int_set = (Set.empty: set (int));
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
@ -63,9 +61,9 @@ let my_set: int_set = (Set.empty: set(int));
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo group=a
|
||||
const contains_three: bool = my_set contains 3;
|
||||
const contains_three : bool = my_set contains 3
|
||||
// or alternatively
|
||||
const contains_three_fn: bool = set_mem(3, my_set);
|
||||
const contains_three_fn: bool = set_mem (3, my_set);
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
@ -84,7 +82,7 @@ let contains_three: bool = Set.mem(3, my_set);
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo group=a
|
||||
const set_size: nat = size(my_set);
|
||||
const set_size: nat = size (my_set)
|
||||
```
|
||||
|
||||
<!--CameLIGO-->
|
||||
@ -94,7 +92,7 @@ let set_size: nat = Set.size my_set
|
||||
|
||||
<!--ReasonLIGO-->
|
||||
```reasonligo group=a
|
||||
let set_size: nat = Set.size(my_set);
|
||||
let set_size: nat = Set.size (my_set);
|
||||
```
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
Loading…
Reference in New Issue
Block a user