The following statements can appear anywhere in the function body.
let statement
The let statement allows local and block-scoped variable declaration.
In Tact, declaring a local variable always requires an initial value. However, the type ascription can be omitted and Tact will try to infer it from the initial value:
Note, that initial value of null can mean both an empty map<K, V> with arbitrary K and V types, and the intentional absence of any other value for the optional type. That’s why whenever you’re declaring an optional or a map<K, V>, you’ll need to explicitly specify the type as it cannot be inferred:
Naming a local variable with underscore _ makes its value considered unused and discarded. This is useful when you don’t need a return value of some function with side effects, and want to explicitly mark the variable as unused. Note, that such wildcard variable name _ cannot be accessed:
return statement
The return statement ends function execution and specifies a value to be returned to the function caller.
Block
A block statement is used to group zero or more statements. The block is delimited by a pair of braces (“curly braces”, {}) and contains a list of zero or more statements and declarations.
Some statements, such as let or return, must end with a terminating semicolon ;. However, the semicolon of the last statement in the block is optional and may be omitted.
Expression
An expression statement is an expression used in a place where a statement is expected. The expression is evaluated and its result is discarded — therefore, it makes sense only for expressions that have side effects, such as executing a function or updating a variable.
The destructuring assignment is a concise way to unpack Structs and Messages into distinct variables. It mirrors the instantiation syntax, but instead of creating a new Struct or Message it binds every field or some of the fields to their respective variables.
The syntax is derived from the let statement, and instead of specifying the variable name directly it involves specifying the structure type on the left side of the assignment operator =, which corresponds to the structure type of the value on the right side.
Just like in instantiation, the trailing comma is allowed.
To create a binding under a different variable name, specify it after the semicolon :.
Note, that the order of bindings doesn’t matter — all the fields retain their values and types under their names no matter the order in which they stand in their definition in the respective Struct or Message.
Destructuring assignment is exhaustive and requires specifying all the fields as variables. To deliberately ignore some of the fields, use an underscore _, which discards the considered field’s value. Note, that such wildcard variable name _ cannot be accessed:
To completely ignore the rest of the fields, use .. at the end of the list:
Branches
Control the flow of the code.
if...else
When executing an if...else statement, first, the specified condition gets evaluated. If the resulting value is true, the following statement block gets executed. Otherwise, if the condition evaluates to false, the optional else block will be executed. If the else block is missing, nothing happens and execution continues further.
Regular if statement:
With else block:
With nested if...else:
try...catch
The try...catch statement is comprised of a try block and an optional catch block, which receives an Intexit code as its only argument. The code in the try block is executed first, and if it fails, the code in the catch block will be executed and changes made in try block will be rolled back, if possible.
Regular try statement:
With catch (e) block:
With nested try...catch:
Note, that similar to let statement, captured exit code in the catch () clause can be discarded by specifying an underscore _ in its place:
Loops
Conditionally repeat certain blocks of code multiple times.
repeat
The repeat loop executes a block of code a specified number of times. The number of repetitions should be given as a positive 32-bit Int in the inclusive range from 1 to 231−1. If the value is greater, an error with the exit code 5, Integer out of the expected range would be thrown.
If the specified number of repetitions is equal to 0 or any negative number in the inclusive range −2256 to −1, it is ignored and the code block is not executed at all.
while
The while loop continues executing the block of code as long as the given condition is true.
In the following example, the value of x is decremented by 1 on each iteration, so the loop will run 10 times:
do...until
The do...until loop is a post-test loop that executes the block of code at least once, and then continues to execute it until the given condition becomes true.
In the following example, the value of x is decremented by 1 on each iteration, so the loop will run 10 times:
foreach
The foreach loop operates on key-value pairs (entries) of map<K, V> type in sequential order: from the smallest keys of the map to the biggest ones.
This loop executes a block of code for each entry in the given map, capturing the key and value on each iteration. This is handy when you don’t know in advance how many items there is in the map or don’t want to explicitly look for each of the entry using .get()method of maps.
Note, that the names of captured key and value pair on each iteration are arbitrary and can be any valid Tact identifier, provided that they’re new to the current scope. The most common options are: k and v, or key and value.
In the following example, map cells has 4 entries, so the loop will run 4 times:
It’s also possible to iterate over a map in contract storage, and over maps as members of instances of Struct or Message types:
Note, that similar to let statement, either of captured key or value (or both) can be discarded by specifying an underscore _ in their place: