The syntax of Rust is the set of rules defining how a Rust program is written and compiled. Rust's syntax is similar to that of C and C++, although many of its features were influenced by functional programming languages such as OCaml.
Basics Although Rust syntax is heavily influenced by the syntaxes of C and C++, the syntax of Rust is far more distinct from C++ syntax than Java or C#, as those languages have more C-style declarations, primitive names, and keywords. Below is a "Hello, World!" program in Rust. The fn keyword denotes a function, and the println! macro (see § Macros) prints the message to standard output. Statements in Rust are separated by semicolons.
Reserved words
Keywords The following 42 words are reserved, and may not be used as identifiers.
Unused words The following words are reserved as keywords, but currently have no use or purpose. There are 14 unused words.
Variables Variables in Rust are defined through the let keyword. The example below assigns a value to the variable with name foo and outputs its value.
Variables are immutable by default, but adding the mut keyword allows the variable to be mutated. The following example uses //, which denotes the start of a comment.
Multiple let expressions can define multiple variables with the same name, known as variable shadowing. Variable shadowing allows transforming variables without having to name the variables differently. The example below declares a new variable with the same name that is double the original value:
Variable shadowing is also possible for values of different types. For example, going from a string to its length in bytes:
Block expressions and control flow A block expression is delimited by curly brackets. When the last expression inside a block does not end with a semicolon, the block evaluates to the value of that trailing expression:
Trailing expressions of function bodies are used as the return value:
if expressions An if conditional expression executes code based on whether the given value is true. else can be used for when the value evaluates to false, and else if can be used for combining multiple expressions.
if and else blocks can evaluate to a value, which can then be assigned to a variable:
while loops while can be used to repeat a block of code while a condition is met.
for loops and iterators For loops in Rust loop over elements of a collection. for expressions work over any iterator type.
In the above code, 4..=10 is a value of type Range which implements the Iterator trait. The code within the curly braces is applied to each element returned by the iterator. Iterators can be combined with functions over iterators like map, filter, and sum. For example, the following adds up all numbers between 1 and 100 that are multiples of 3:
loop and break statements More generally, the loop keyword allows repeating a portion of code until a break occurs. break may optionally exit the loop with a value. In the case of nested loops, labels denoted by 'label_name can be used to break an outer loop rather than the innermost loop.
Pattern matching The match and if let expressions can be used for pattern matching. For example, match can be used to double an optional integer value if present, and return zero otherwise:
Equivalently, this can be written with if let and else:
Types Rust is strongly typed and statically typed, meaning that the types of all variables must be known at compilation time. Assigning a value of a particular type to a differently typed variable causes a compilation error. Type inference is used to determine the type of variables if unspecified. The type (), called the "unit type" in Rust, is a concrete type that has exactly one value (itself). It occupies no memory (as it represents the absence of value). All functions that do not have an indicated return type implicitly return (). It is similar to void in other C-style languages, however void denotes the absence of a type and cannot have any value. The default integer type is i32, and the default floating point type is f64. If the type of a literal number is not explicitly provided, it is either inferred from the context or the default type is used.
Primitive types Integer types in Rust are named based on the signedness and the number of bits the type takes. For example, i32 is a signed integer that takes 32 bits of storage, whereas u8 is unsigned and only takes 8 bits of storage. isize and usize take storage depending on the architecture of the computer that runs the code, for example, on computers with 32-bit architectures, both types will take up 32 bits of space. By default, integer literals are in base-10, but different radices are supported with prefixes, for example, 0b11 for binary numbers, 0o567 for octals, and 0xDB for hexadecimals. By default, integer literals default to i32 as its type. Suffixes such as 4u32 can be used to explicitly set the type of a literal. Byte literals such as b'X' are available to represent the ASCII value (as a u8) of a specific character. The Boolean type is referred to as bool which can take a value of either true or false. A char takes up 32 bits of space and represents a Unicode scalar value: a Unicode codepoint that is not a surrogate. IEEE 754 floating point numbers are supported with f32 for single precision floats and f64 for double precision floats.
Compound types Compound types can contain multiple values. Tuples are fixed-size lists that can contain values whose types can be different. Arrays are fixed-size lists whose values are of the same type. Expressions of the tuple and array types can be written through listing the values, and can be accessed with .index or [index]:
Arrays can also be constructed through copying a single value a number of times:
Ownership and references Rust's ownership system consists of rules that ensure memory safety without using a garbage collector. At compile time, each value must be attached to a variable called the owner of that value, and every value must have exactly one owner. Values are moved between different owners through assignment or passing a value as a function parameter. Values can also be borrowed, meaning they are temporarily passed to a different function before being returned to the owner. With these rules, Rust can prevent the creation and use of dangling pointers:
The function print_string takes ownership over the String value passed in; Alternatively, & can be used to indicate a reference type (in &String) and to create a reference (in &s):
… excerpt ends here. Continue reading the full article.



