Book
Statements

Statements

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 variable always requires an initial value and an explicit type:

let value: Int = 123;           // declaration
let valueOptional: Int? = null; // Int or null
 
let valueMap: map<Int, Int> = emptyMap();
let valueMapWithSerialization: map<Int as uint8, Int as uint8> = emptyMap();

return statement

The return statement ends function execution and specifies a value to be returned to the function caller.

// Simple wrapper over stdlib function now()
fun getTimeFromNow(offset: Int): Int {
    return now() + offset;
}

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.

{ // <- start of the block
    // arbitrary statements:
    let value: Int = 2 + 2;
    dump(value);
} // <- end of the block
 
{ dump(2 + 2); } // a block with only one statement

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.

dump(2 + 2); // stdlib function

Assignment

Assignment statements use an assignment operator (=) or augmented assignment operators (assignments combined with an operation):

let value: Int; // declaration
value = 5;      // assignment
value += 5;     // augmented assignment (one of the many, see below)
💡

Read more about assignment and augmented assignment in their dedicated section: assignment operators.

Branches

Control the flow of the code.

if...else

⚠️

Curly brackets (code blocks) are required!

When executing an if...else statement, first, the specified condition gets evaluated. If the resulting value is true, the then statement block gets executed. Otherwise, if the condition evaluates to false, the optional else statement block will be executed. If the else block is missing, nothing happens and execution continues further.

Regular if-statement:

// condition
// ↓
if (true) { // consequence, when condition is true
    dump(2 + 2);
}

With else clause:

// condition
// ↓
if (2 + 2 == 4) {
    // consequence, when condition is true
    dump(true);
} else {
    // alternative, when condition is false
    dump(false);
}

With nested if...else:

// condition
// ↓
if (2 + 2 == 3) {
    // consequence, when condition is true
    dump("3?");
//        condition2
//        ↓
} else if (2 + 2 == 4) {
    // another consequence, when condition2 is true
    dump(true);
} else {
    // alternative, when both condition and condition2 are false
    dump(false);
}
💡

Tact also has a ternary expression ?:, which is described earlier in the Book: Ternary.

Loops

Conditionally repeat certain blocks of code multiple times.

repeat

The repeat loop executes a block of code a specified number of times. Number of repetitions must be a non-negative 3232-bit Int. Otherwise an error with the exit code 5, Integer out of the expected range would be thrown.

In the following example, code inside the loop will be executed 1010 times:

let twoPow: Int = 1;
repeat (10) {  // repeat exactly 10 times
    twoPow *= 2;
}

while

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 11 on each iteration, so the loop will run 1010 times:

let x: Int = 10;
while (x > 0) {
    x -= 1;
}

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 11 on each iteration, so the loop will run 1010 times:

let x: Int = 10;
do {
    x -= 1;  // executes this code block at least once
} until (x <= 0);
💡