Improvements from Sander and JDP.
This commit is contained in:
parent
61ec0f41c3
commit
3583f72cb4
@ -386,13 +386,14 @@ type return = (list (operation), storage);
|
||||
|
||||
let dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address);
|
||||
|
||||
let proxy = ((param, store): (parameter, storage)) : return =>
|
||||
let proxy = ((param, store): (parameter, storage)) : return => {
|
||||
let counter : contract (parameter) = Operation.get_contract (dest);
|
||||
(* Reuse the parameter in the subsequent
|
||||
transaction or use another one, `mock_param`. *)
|
||||
let mock_param : parameter = Increment (5n);
|
||||
let op : operation = Operation.transaction (param, 0mutez, counter);
|
||||
([op], store);
|
||||
([op], store)
|
||||
};
|
||||
```
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
@ -101,8 +101,8 @@ let in_24_hrs : timestamp = today - one_day;
|
||||
|
||||
### Comparing Timestamps
|
||||
|
||||
You can also compare timestamps using the same comparison operators as
|
||||
for numbers.
|
||||
You can compare timestamps using the same comparison operators
|
||||
applying to numbers.
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
@ -124,10 +124,10 @@ let not_tomorrow : bool = (Current.time == in_24_hrs);
|
||||
|
||||
## Addresses
|
||||
|
||||
The type `address` in LIGO is used to denote Tezos addresses (tz1,
|
||||
tz2, tz3, KT1, ...). Currently, addresses are created by casting a
|
||||
string to the type `address`. Beware of failures if the address is
|
||||
invalid. Consider the following examples.
|
||||
The type `address` in LIGO denotes Tezos addresses (tz1, tz2, tz3,
|
||||
KT1, ...). Currently, addresses are created by casting a string to the
|
||||
type `address`. Beware of failures if the address is invalid. Consider
|
||||
the following examples.
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
@ -152,7 +152,7 @@ let my_account : address =
|
||||
|
||||
## Signatures
|
||||
|
||||
The type `signature` in LIGO datatype is used for Tezos signature
|
||||
The `signature` type in LIGO datatype is used for Tezos signatures
|
||||
(edsig, spsig). Signatures are created by casting a string. Beware of
|
||||
failure if the signature is invalid.
|
||||
|
||||
@ -181,7 +181,7 @@ signature);
|
||||
|
||||
## Keys
|
||||
|
||||
The type `key` in LIGO is used for Tezos public keys. Do not confuse
|
||||
The `key` type in LIGO is used for Tezos public keys. Do not confuse
|
||||
them with map keys. Keys are made by casting strings. Beware of
|
||||
failure if the key is invalid.
|
||||
|
||||
|
@ -34,7 +34,10 @@ In LIGO, only values of the same type can be compared. Moreover, not
|
||||
all values of the same type can be compared, only those with
|
||||
*comparable types*, which is a concept lifted from
|
||||
Michelson. Comparable types include, for instance, `int`, `nat`,
|
||||
`string`, `tez`, `timestamp`, `address`, etc.
|
||||
`string`, `tez`, `timestamp`, `address`, etc. As an example of
|
||||
non-comparable types: maps, sets or lists are not comparable: if you
|
||||
wish to compare them, you will have to write your own comparison
|
||||
function.
|
||||
|
||||
### Comparing Strings
|
||||
|
||||
@ -110,7 +113,7 @@ let h : bool = (a != b);
|
||||
```pascaligo group=d
|
||||
const a : tez = 5mutez
|
||||
const b : tez = 10mutez
|
||||
const c : bool = (a = b) // false
|
||||
const c : bool = (a = b) // False
|
||||
```
|
||||
<!--CameLIGO-->
|
||||
```cameligo group=d
|
||||
@ -129,7 +132,7 @@ let c : bool = (a == b); // false
|
||||
|
||||
## Conditionals
|
||||
|
||||
Conditional logic enables to fork the control flow depending on the
|
||||
Conditional logic enables forking the control flow depending on the
|
||||
state.
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
|
@ -10,11 +10,11 @@ logic into functions.
|
||||
## Blocks
|
||||
|
||||
In PascaLIGO, *blocks* enable the sequential composition of
|
||||
*instructions* into an isolated scope. Each `block` needs to include
|
||||
at least one instruction. If we need a placeholder *placeholder*, we
|
||||
use the instruction called `skip`, that leaves the state
|
||||
invariant. The rationale for `skip` instead of a truly empty block is
|
||||
that it prevents you from writing an empty block by mistake.
|
||||
instructions into an isolated scope. Each block needs to include at
|
||||
least one instruction. If we need a placeholder, we use the
|
||||
instruction `skip` which leaves the state unchanged. The rationale
|
||||
for `skip` instead of a truly empty block is that it prevents you from
|
||||
writing an empty block by mistake.
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
@ -31,10 +31,10 @@ Blocks are more versatile than simply containing instructions:
|
||||
they can also include *declarations* of values, like so:
|
||||
```pascaligo skip
|
||||
// terse style
|
||||
block { const a : int = 1; }
|
||||
block { const a : int = 1 }
|
||||
// verbose style
|
||||
begin
|
||||
const a : int = 1;
|
||||
const a : int = 1
|
||||
end
|
||||
```
|
||||
|
||||
|
@ -64,7 +64,7 @@ to have a special type: if the type of the accumulator is `t`, then it
|
||||
must have the type `bool * t` (not simply `t`). It is the boolean
|
||||
value that denotes whether the stopping condition has been reached.
|
||||
|
||||
```cameligo group=b
|
||||
```cameligo group=a
|
||||
let iter (x,y : nat * nat) : bool * (nat * nat) =
|
||||
if y = 0n then false, (x,y) else true, (y, x mod y)
|
||||
|
||||
@ -77,7 +77,7 @@ let gcd (x,y : nat * nat) : nat =
|
||||
To ease the writing and reading of the iterated functions (here,
|
||||
`iter`), two predefined functions are provided: `continue` and `stop`:
|
||||
|
||||
```cameligo group=c
|
||||
```cameligo group=a
|
||||
let iter (x,y : nat * nat) : bool * (nat * nat) =
|
||||
if y = 0n then stop (x,y) else continue (y, x mod y)
|
||||
|
||||
@ -113,27 +113,29 @@ accumulator is `t`, then it must have the type `bool * t` (not simply
|
||||
`t`). It is the boolean value that denotes whether the stopping
|
||||
condition has been reached.
|
||||
|
||||
```reasonligo group=d
|
||||
```reasonligo group=a
|
||||
let iter = ((x,y) : (nat, nat)) : (bool, (nat, nat)) =>
|
||||
if (y == 0n) { (false, (x,y)); } else { (true, (y, x mod y)); };
|
||||
|
||||
let gcd = ((x,y) : (nat, nat)) : nat =>
|
||||
let gcd = ((x,y) : (nat, nat)) : nat => {
|
||||
let (x,y) = if (x < y) { (y,x); } else { (x,y); };
|
||||
let (x,y) = Loop.fold_while (iter, (x,y));
|
||||
x;
|
||||
x
|
||||
};
|
||||
```
|
||||
|
||||
To ease the writing and reading of the iterated functions (here,
|
||||
`iter`), two predefined functions are provided: `continue` and `stop`:
|
||||
|
||||
```reasonligo group=e
|
||||
```reasonligo group=b
|
||||
let iter = ((x,y) : (nat, nat)) : (bool, (nat, nat)) =>
|
||||
if (y == 0n) { stop ((x,y)); } else { continue ((y, x mod y)); };
|
||||
|
||||
let gcd = ((x,y) : (nat, nat)) : nat =>
|
||||
let gcd = ((x,y) : (nat, nat)) : nat => {
|
||||
let (x,y) = if (x < y) { (y,x); } else { (x,y); };
|
||||
let (x,y) = Loop.fold_while (iter, (x,y));
|
||||
x;
|
||||
x
|
||||
};
|
||||
```
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
@ -147,7 +149,7 @@ To iterate over a range of integers you use a loop of the form `for
|
||||
familiar for programmers of imperative languages. Note that, for the
|
||||
sake of generality, the bounds are of type `int`, not `nat`.
|
||||
|
||||
```pascaligo group=f
|
||||
```pascaligo group=c
|
||||
function sum (var n : nat) : int is block {
|
||||
var acc : int := 0;
|
||||
for i := 1 to int (n) block {
|
||||
@ -177,7 +179,7 @@ of the form `for <element var> in <collection type> <collection var>
|
||||
|
||||
Here is an example where the integers in a list are summed up.
|
||||
|
||||
```pascaligo group=g
|
||||
```pascaligo group=d
|
||||
function sum_list (var l : list (int)) : int is block {
|
||||
var total : int := 0;
|
||||
for i in list l block {
|
||||
@ -197,7 +199,7 @@ gitlab-pages/docs/language-basics/src/loops/collection.ligo sum_list
|
||||
|
||||
Here is an example where the integers in a set are summed up.
|
||||
|
||||
```pascaligo=g
|
||||
```pascaligo=e
|
||||
function sum_set (var s : set (int)) : int is block {
|
||||
var total : int := 0;
|
||||
for i in set s block {
|
||||
|
@ -358,7 +358,7 @@ let moves : register =
|
||||
let moves : register =
|
||||
Map.literal ([
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3)),]);
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
|
||||
```
|
||||
|
||||
> The `Map.literal` predefined function builds a map from a list of
|
||||
@ -377,8 +377,8 @@ example:
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
```pascaligo group=f
|
||||
(*const my_balance : option (move) =
|
||||
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)] *)
|
||||
const my_balance : option (move) =
|
||||
moves [("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)]
|
||||
```
|
||||
|
||||
<!--Cameligo-->
|
||||
@ -418,11 +418,12 @@ let force_access (key, moves : address * register) : move =
|
||||
```
|
||||
|
||||
<!--Reasonligo-->
|
||||
```reasonlig group=f
|
||||
let force_access : ((key, moves) : address * register) : move => {
|
||||
switch (Map.find_opt key moves) with
|
||||
Some move -> move
|
||||
| None -> (failwith "No move." : move)
|
||||
```reasonligo group=f
|
||||
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-->
|
||||
@ -475,9 +476,8 @@ let assign (m : register) : register =
|
||||
```
|
||||
|
||||
> 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 only
|
||||
> defined on its key, but not its value. This encoding enables
|
||||
> partially defined bindings.
|
||||
> use `None` instead, that would have meant that the binding is
|
||||
> removed.
|
||||
|
||||
<!--Reasonligo-->
|
||||
|
||||
@ -492,9 +492,8 @@ let assign = (m : register) : register => {
|
||||
```
|
||||
|
||||
> 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 only
|
||||
> defined on its key, but not its value. This encoding enables
|
||||
> partially defined bindings.
|
||||
> use `None` instead, that would have meant that the binding is
|
||||
> removed.
|
||||
|
||||
<!--END_DOCUSAURUS_CODE_TABS-->
|
||||
|
||||
@ -601,7 +600,7 @@ let map_op = (m : register) : register => {
|
||||
A *fold operation* is the most general of iterations. The iterated
|
||||
function takes two arguments: an *accumulator* and the structure
|
||||
*element* at hand, with which it then produces a new accumulator. This
|
||||
enables to have a partial result that becomes complete when the
|
||||
enables having a partial result that becomes complete when the
|
||||
traversal of the data structure is over.
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
@ -622,7 +621,7 @@ let fold_op (m : register) : register =
|
||||
|
||||
<!--Reasonligo-->
|
||||
```reasonligo group=f
|
||||
let fold_op = (m: register): register => {
|
||||
let fold_op = (m : register) : register => {
|
||||
let aggregate = ((i,j): (int, (address, move))) => i + j[1][1];
|
||||
Map.fold (aggregate, m, 5);
|
||||
};
|
||||
@ -703,7 +702,7 @@ let moves : register =
|
||||
let moves : register =
|
||||
Big_map.literal ([
|
||||
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3)),]);
|
||||
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
|
||||
```
|
||||
|
||||
> The predefind function `Big_map.literal` constructs a big map from a
|
||||
|
@ -8,15 +8,14 @@ LIGO offers three built-in numerical types: `int`, `nat` and `tez`.
|
||||
## Addition
|
||||
|
||||
Addition in LIGO is accomplished by means of the `+` infix
|
||||
operator. Some type constraints apply, for example you ca not add a
|
||||
operator. Some type constraints apply, for example you cannot add a
|
||||
value of type `tez` to a value of type `nat`.
|
||||
|
||||
In the following example you can find a series of arithmetic
|
||||
operations, including various numerical types. However, some bits
|
||||
remain in comments because they would otherwise not compile because,
|
||||
for example, adding a value of type `int` to a value of type `tez` is
|
||||
invalid. Note that adding an integer to a natural number produces an
|
||||
integer.
|
||||
remain in comments as they would otherwise not compile, for example,
|
||||
adding a value of type `int` to a value of type `tez` is invalid. Note
|
||||
that adding an integer to a natural number produces an integer.
|
||||
|
||||
<!--DOCUSAURUS_CODE_TABS-->
|
||||
<!--Pascaligo-->
|
||||
@ -115,7 +114,7 @@ let g : int = 1_000_000;
|
||||
|
||||
## Subtraction
|
||||
|
||||
Subtraction looks like as follows.
|
||||
Subtraction looks as follows.
|
||||
|
||||
> ⚠️ Even when subtracting two `nats`, the result is an `int`
|
||||
|
||||
|
@ -0,0 +1,6 @@
|
||||
type coin = Head | Tail
|
||||
|
||||
let flip (c : coin) : coin =
|
||||
match c with
|
||||
Head -> Tail
|
||||
| Tail -> Head
|
@ -0,0 +1,7 @@
|
||||
type coin = | Head | Tail;
|
||||
|
||||
let flip = (c : coin) : coin =>
|
||||
switch (c) {
|
||||
| Head => Tail
|
||||
| Tail => Head
|
||||
};
|
Loading…
Reference in New Issue
Block a user