Statements
This content is not available in your language yet.
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.
Assignment
Assignment statements use an assignment operator (=
) or augmented assignment operators (assignments combined with an operation):
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 Int
exit 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 -bit Int
in the inclusive range from to . 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 or any negative number in the inclusive range to , 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 on each iteration, so the loop will run 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 on each iteration, so the loop will run 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 entries, so the loop will run 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: