Skip to content
This repository was archived by the owner on Dec 12, 2024. It is now read-only.

Commit ccdf9a5

Browse files
authored
Merge branch 'main' into virtual-function
2 parents 10a0496 + 5a82ca0 commit ccdf9a5

10 files changed

+494
-100
lines changed

pages/book/contracts.mdx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,6 @@ contract Example {
8080
const StateDelivered: Int = 2;
8181
const StateDisputed: Int = 3;
8282
83-
// no need to init constants
84-
init() {}
85-
8683
get fun sum(): Int {
8784
// access constants from anywhere
8885
return GlobalConst1 + self.ContractConst1 + self.StatePaid;
@@ -111,6 +108,14 @@ contract Example {
111108
}
112109
```
113110

111+
If a contract doesn't have any persistent state variables, or they all have their default value specified, it may omit the `init(){:tact}` function declaration altogether. That's because unless explicitly declared, the empty `init(){:tact}` function is present by default in all contracts.
112+
113+
The following is an example of a valid empty contract:
114+
115+
```tact
116+
contract IamEmptyAndIknowIt {}
117+
```
118+
114119
<Callout>
115120

116121
To obtain initial state of the target contract in [internal functions](#internal-functions), [receivers](#receiver-functions) or [getters](#getter-functions) use [`initOf{:tact}`](/book/expressions#initof) expression.
@@ -201,7 +206,6 @@ They can only be called from [receivers](#receiver-functions), [getters](#getter
201206
```tact
202207
contract Functions {
203208
val: Int = 0;
204-
init() {}
205209
206210
// this contract method can only be called from within this contract and access its variables
207211
fun onlyZeros() {

pages/book/exit-codes.mdx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,7 @@ Example:
175175
1. First, define an empty contract like below:
176176

177177
```tact
178-
contract Fireworks {
179-
init() {}
180-
}
178+
contract Fireworks {}
181179
```
182180

183181
2. Then, send a message to this contract. Because no suitable operation is found, you will get this exit code.
@@ -301,4 +299,4 @@ Example:
301299
// fun newAddress(chain: Int, hash: Int): Address;
302300
// creates a new address from chain and hash values.
303301
let zeroAddress: Address = newAddress(-1, 0); // masterchain zero address
304-
```
302+
```

pages/book/expressions.mdx

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,69 @@ Read more about booleans and [`Bool{:tact}`](/book/types#booleans) type in the d
6868
A string literal is zero or more characters enclosed in double (`"`) quotation marks. All string literals are objects of [`String{:tact}`][p] type.
6969

7070
```tact
71-
"foo"
72-
"1234"
71+
"foo";
72+
"1234";
73+
```
74+
75+
Tact strings support a range of [escape sequences](https://en.wikipedia.org/wiki/Escape_sequence) starting with a backslash `\\` character:
76+
77+
* `\\{:tact}` — literal backslash
78+
* `\"{:tact}` — double quote
79+
* `\n{:tact}` — newline
80+
* `\r{:tact}` — carriage return
81+
* `\t{:tact}` — tab
82+
* `\v{:tact}` — vertical tab
83+
* `\b{:tact}` — backspace
84+
* `\f{:tact}` — form feed
85+
* `\x00{:tact}` through `\xFF{:tact}`[code point](https://en.wikipedia.org/wiki/Code_point), must be exactly two hex digits long
86+
* `\u0000{:tact}` through `\uFFFF{:tact}`[Unicode code point][unicode], must be exactly four hex digits long
87+
* `\u{0}{:tact}` through `\u{FFFFFF}{:tact}`[Unicode code point][unicode], can be from $1$ to $6$ hex digits long
88+
89+
[unicode]: https://en.wikipedia.org/wiki/Unicode#Codespace_and_code_points
90+
91+
```tact
92+
// \\
93+
"escape \\ if \\ you \\ can \\";
94+
95+
// \"
96+
"this \"literally\" works";
97+
98+
// \n
99+
"line \n another line";
100+
101+
// \r
102+
"Shutters \r Like \r This \r One";
73103
74-
// Note, that at the moment Tact strings can't have escape characters in them:
75-
"line \n another"; // SYNTAX ERROR!, see: https://github.com/tact-lang/tact/issues/25
104+
// \t
105+
"spacing \t granted!";
76106
77-
// This means, that double quotes inside strings are also prohibited:
78-
"this \"can't be!\""; // SYNTAX ERROR!
107+
// \v
108+
"those \v words \v are \v aligned";
109+
110+
// \b
111+
"rm\b\bcreate!";
112+
113+
// \f
114+
"form \f feed";
115+
116+
// \x00 - \xFF
117+
"this \x22literally\x22 works"; // \x22 represents a double quote
118+
119+
// \u0000 - \uFFFF
120+
"danger, \u26A1 high voltage \u26A1"; // \u26A1 represents the ⚡ emoji
121+
122+
// \u{0} - \u{FFFFFF}
123+
"\u{1F602} LOL \u{1F602}"; // \u{1F602} represents the 😂 emoji
79124
```
80125

81-
Read more about strings and [`String{:tact}`][p] type there: [Primitive types][p].
126+
<Callout>
127+
128+
Read more about strings and [`String{:tact}`][p] type:\
129+
[Primitive types in the Book][p]\
130+
[Strings and StringBuilders in the Reference](/ref/api-strings)
131+
132+
</Callout>
133+
82134

83135
### `null` literal
84136

@@ -156,7 +208,6 @@ Anywhere in the function body, a global [static function](/book/functions#global
156208

157209
```tact
158210
contract ExampleContract {
159-
init() {}
160211
receive() {
161212
now(); // now() is a static function of stdlib
162213
let expiration: Int = now() + 1000; // operation and variable declaration

pages/book/functions.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Extension functions allow you to implement extensions for any possible type.
5656
> The name of the first argument MUST be named `self` and the type of this argument is the type you are extending.
5757
5858
```tact
59-
extends fun pow(self: Int, c: Int) {
59+
extends fun pow(self: Int, c: Int): Int {
6060
let res: Int = 1;
6161
repeat(c) {
6262
res *= self;

pages/book/maps.mdx

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Allowed value types:
3030

3131
## Operations
3232

33-
### Declare
33+
### Declare, `emptyMap()` [#emptymap]
3434

3535
As a [local variable](/book/statements#let), using `emptyMap(){:tact}` function of standard library:
3636

@@ -93,9 +93,9 @@ if (gotButUnsure != null) {
9393
}
9494
```
9595

96-
### Delete entries [#del]
96+
### Delete entries, `.del()` [#del]
9797

98-
To delete a single key-value pair (single entry), simply assign the `null{:tact}` value to the key when using the [`.set(){:tact}`](#set) [method](/book/functions#extension-function).
98+
To delete a single key-value pair (single entry), use the `.del(){:tact}` [method](/book/functions#extension-function). It returns `true{:tact}` in the case of successful deletion and `false{:tact}` otherwise.
9999

100100
```tact
101101
// Empty map
@@ -106,7 +106,13 @@ fizz.set(7, 123);
106106
fizz.set(42, 321);
107107
108108
// Deleting one of the keys
109-
fizz.set(7, null); // the entry under key 7 is now deleted
109+
let deletionSuccess: Bool = fizz.del(7); // true, because map contained the entry under key 7
110+
fizz.del(7); // false, because map no longer has an entry under key 7
111+
112+
// Note, that assigning the `null` value to the key when using the `.set()` method
113+
// is equivalent to calling `.del()`, although such approach is much less descriptive
114+
// and is generally discouraged:
115+
fizz.set(42, null); // the entry under key 42 is now deleted
110116
```
111117

112118
To delete all the entries from the map, re-assign the map using the `emptyMap(){:tact}` function:
@@ -126,7 +132,25 @@ fizz = null; // identical to the previous line, but less descriptive
126132

127133
With this approach all previous entries of the map are completely discarded from the contract even if the map was declared as its persistent state variable. As a result, assigning maps to `emptyMap(){:tact}` **does not** inflict any hidden or sudden [storage fees](https://docs.ton.org/develop/smart-contracts/fees#storage-fee).
128134

129-
### Convert to a `Cell`, `.asCell()` [#convert]
135+
### Check if empty, `.isEmpty()` [#isempty]
136+
137+
The `.isEmpty(){:tact}` [method](/book/functions#extension-function) on maps returns `true{:tact}` if the map is empty and `false{:tact}` otherwise:
138+
139+
```tact
140+
let fizz: map<Int, Int> = emptyMap();
141+
142+
if (fizz.isEmpty()) {
143+
dump("Empty maps are empty, duh!");
144+
}
145+
146+
// Note, that comparing the map to `null` behaves the same as `.isEmpty()` method,
147+
// although such direct comparison is much less descriptive and is generally discouraged:
148+
if (fizz == null) {
149+
dump("Empty maps are null, which isn't obvious");
150+
}
151+
```
152+
153+
### Convert to a `Cell`, `.asCell()` [#ascell]
130154

131155
Use `.asCell(){:tact}` [method](/book/functions#extension-function) on maps to convert all their values to a [`Cell{:tact}`][p] type. Be mindful, that [`Cell{:tact}`][p] type is able to store up to 1023 bits, so converting larger maps to the Cell will result in error.
132156

@@ -157,7 +181,25 @@ contract Example {
157181

158182
### Traverse over entries [#traverse]
159183

160-
At the moment Tact doesn't have a special syntax for iterating over maps. However, it's possible to use maps as a simple arrays if you define a `map<Int, v>{:tact}` with an [`Int{:tact}`][int] type for the keys and keep track of the number of items in the separate variable:
184+
To iterate over map entries there is a [`foreach{:tact}`](/book/statements#foreach-loop) loop statement:
185+
186+
```tact
187+
// Empty map
188+
let fizz: map<Int, Int> = emptyMap();
189+
190+
// Setting a couple of values under different keys
191+
fizz.set(42, 321);
192+
fizz.set(7, 123);
193+
194+
// Iterating over in a sequential order: from the smallest keys to the biggest ones
195+
foreach (key, value in fizz) {
196+
dump(key); // will dump 7 on the first iteration, then 42 on the second
197+
}
198+
```
199+
200+
Read more about it: [`foreach{:tact}` loop in Book→Statements](/book/statements#foreach-loop).
201+
202+
Note, that it's also possible to use maps as simple arrays if you define a `map<Int, V>{:tact}` with an [`Int{:tact}`][int] type for the keys, any allowed `V` type for values and keep track of the number of items in the separate variable:
161203

162204
```tact
163205
contract Iteration {
@@ -265,9 +307,6 @@ contract Example {
265307
arr: map<Int, Int>; // "array" of String values as a map
266308
arrLength: Int = 0; // length of the "array", defaults to 0
267309
268-
// Constructor (initialization) function of the contract
269-
init() {}
270-
271310
// Internal function for pushing an item to the end of the "array"
272311
fun arrPush(item: String) {
273312
if (self.arrLength >= self.MaxMapSize) {

pages/book/message-mode.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ $+32$ | `SendDestroyIfZero{:tact}` | Current account must be destroyed
2525

2626
## Combining modes with flags
2727

28-
To make the [`Int{:tact}`][int] value for `mode` field of SendParameters, you just have to combine base modes with optional flags by applying the [`bitwise OR{:tact}`](/book/operators#binary-bitwise-or) operation.
28+
To make the [`Int{:tact}`][int] value for `mode` field of `SendParameters{:tact}`, you just have to combine base modes with optional flags by applying the [`bitwise OR{:tact}`](/book/operators#binary-bitwise-or) operation.
2929

3030
For example, if you want to send a regular message and pay transfer fees separately, use the mode $0$ (default) and a flag $+1$ to get `mode` $= 1$, which is equal to using `SendPayGasSeparately{:tact}` constant.
3131

0 commit comments

Comments
 (0)