Rust Essentials(Second Edition)
上QQ阅读APP看书,第一时间看更新

Expressions

Rust is an expression-oriented language, which means that most pieces of code are in fact expressions, that is, they compute a value and return that value. However, expressions on themselves do not form meaningful code; they must be used in statements.

let bindings like the following are declaration statements; they are not expressions:

// see Chapter 2/code/expressions.rs 
let a = 2;    // a binds to 2 
let b = 5;    // b binds to 5 
let n = a + b;   // n binds to 7 

But, here, a + b is an expression and, if we omit the semicolon at the end, the resulting value (here the value 7) is returned. This is often used when a function needs to return its value (see examples in the next chapter). Ending an expression with a semicolon like a + b; suppresses this behaviour, thus throwing away the return value and making it an expression statement returning the unit value ().

Code is usually a sequence of statements, one on each code line and Rust has to know when a statement ends, that's why nearly every Rust code line ends with a semicolon.

What do you think the assignment m = 42; is? It is not a binding, because there is no let binding (that should have happened on a previous code line). It is an expression that returns the unit value ().

A compound binding like let p = q = 3; is not allowed in Rust, it returns the following error:

error: unresolved name q

However, you can chain let bindings like this:

let mut n = 0; 
let mut m = 1; 
let t = m; m = n; n  = t; 
println!("{} {} {}", n, m, t); // 

This gives an output as: 1 0 1

Exercise:

Print out the values of a, b, and n after this code snippet. Explain the value of a(For an example code, seecompound_let.rs):

let mut a = 5;
let mut b = 6;
let n = 7;
let a = b = n;

A code block is also an expression, which returns the value of its last expression if we omit the semicolon. For example, in the following code snippet, n1 gets the value 7, but n2 gets no value (or, rather, the unit value ()), because the return value of the second block was suppressed:

let n1 = { 
let a = 2; 
let b = 5; 
a + b   // <-- no semicolon! 
}; 
  println!("n1 is: {}", n1);  // prints: n1 is 7 
  let n2 = { 
    let a = 2; 
    let b = 5; 
    a + b; 
  }; 
  println!("n2 is: {:?}", n2);  // prints: n2 is () 

The variables a and b are here declared in a code block and live only as long as the block itself, they are local to the block. Note that the semicolon after the closing brace of the block, };, is needed. To print out the unit value (), we need {:?} as format specifier.