Function body elements¶
A body of a function consists of sequence of elements. Here are listed most important of these elements.
Auto variable declaration¶
See auto variables.
Simple expression¶
Usually this is needed in order to call some function with side-effects.
Foo(); // Call a function, that may have side-effects
Add( 5, 7 ); // Call a function with or without side-effects
Assignment¶
Assignment consists of left part - for destination and right part - for source.
x = 2; // Assign a numeric value to a variable
x = Foo() + Bar() - 66; // Assign a complex expression result to a variable
Min( x, y )= 0; // It's possible too, if the result of "Min" function is a mutable reference
Operation combined with assignment¶
There are following operations combined with assignment:
+=
- addition-=
- subtraction*=
- multiplication/=
- division%=
- remainder&=
- bitwise AND|=
- bitwise OR^=
- bitwise XOR=<<
- left shift=>>
- right shift
An operation with assignment is equivalent to a call to corresponding binary operator for left and right parts of the operation with following assignment of the result to the left part.
x += 2; // Increase value of "x" by 2
x /= Foo() + Bar() - 66; // Divide variable "x" by the result of the right expression and than save result into "x"
Min( x, y ) &= 0xFF; // Set upper bits of the "Min" call result variable to zero
Increment and Decrement¶
++
increases the result of an integer expressions by one, --
decreases it.
++ x;
-- x;
++ Min( x, y );
Control flow elements¶
See Control flow.
static_assert¶
See static_assert.
Block¶
A block consists of sequence of elements in {}
.
It may include elements listed above and other blocks.
A block is used primary for new variables scope creation. A variable defined in a block is visible inside this block and nested blocks. Variables defined in a block have a lifetime limited to the end of this block. When control flow reaches the end of the block lifetimes of all variables defined in this block end.
It’s possible to define inside a block a variable with the same name as in one of outer blocks. After that outer variable will no longer be accessible.
fn Foo()
{
var i32 mut x= 0;
{
++x; // Modify value of outer variable
var f64 mut x= 3.14; // Define a variable with the same name as a variable in outer block. Now the outer "x" variable will not be accessible until the end of the current block.
x= 0.0; // Modify a variable of this block.
var i32 mut y= 0;
}
--y; // Error - name "y" not found
}
A block may have a label.
This label may be used in break
operators inside this block.
In such case break
works for this block only if a label is specified in it.
break
without a label relates to a current loop, but not to a block marked with a label.
continue
for a label of a block is not possible, the compiler will produce an error in such case.
fn Foo(bool cond)
{
{
if( cond )
{
break label block_end;
}
// some other code
} label block_end
}
There are also unsafe
blocks.
See Unsafe code.
with operator¶
This operator allows to perform some action with a result of an expression and if necessary extend the lifetime of temporary variables inside this expression. This operator contains optional reference and mutability modifiers and a name for the expression result.
with
is helpful to use as an alternative to a block, inside that a variable is defined and some operations with it are performed, in cases where the lifetime of the variable should be limited.
Also it is helpful to use with
in template code where it is not clear whether a result of an expression is a variable or a reference, because with
(unlike var
and auto
) allows to create a reference to a temporary variable.
Usage examples:
with( x : Foo() )
{
Bar(x);
return x + 1;
}
with( &mut x : s.Get() )
{
++x;
}