liveBook · Manning

Expression-based language

As explained in Rust in Action: Systems programming concepts and techniques

An expression-based language treats expressions as constructs that produce values and can generally be composed wherever values are expected.

An expression-based language treats expressions as value-producing constructs. In Rust, almost everything is an expression, so expressions can be composed wherever a value is expected. section 2.4.6

Rust makes this idea practical in several familiar constructs:

  • Assign a variable from an if expression, with each branch producing a value. section 2.4.6
  • Use match expressions to choose among value-producing branches. section 2.4.6
  • Return a value from a function by leaving its final expression without a semicolon; the return keyword remains available when needed. section 1.5 section 2.4.6
  • Use break with a value to make a loop produce a result. section 2.4.6

Statements are the boundary: semicolon-delimited expression statements, assignments, and declarations do not produce ordinary values. Rust represents no value with the unit type (). Unlike languages with truthy or falsey values, Rust requires conditions to be exactly true or false. section 2.4.6

Choosing a description with an expression

A conditional can directly initialize a variable: `let description = if is_even(n) { "even" } else { "odd" };`. The matching branches produce the value assigned to `description`, which can then be printed. section 2.4.6

Listing 1.2 Example of Rust code showing some basic processing of CSV data
 fn main() {                                           #1
   let penguin_data = "\                               #2
   common name,length (cm)
   Little penguin,33
   Yellow-eyed penguin,65
   Fiordland penguin,60
   Invalid,data
   ";
 
   let records = penguin_data.lines();
 
   for (i, record) in records.enumerate() {
     if i == 0 || record.trim().len() == 0 {           #3
       continue;
     }
 
     let fields: Vec<_> = record                       #4
       .split(',')                                     #5
       .map(|field| field.trim())                      #6
       .collect();                                     #7
     if cfg!(debug_assertions) {                       #8
       eprintln!("debug: {:?} -> {:?}",
              record, fields);                         #9
     }
 
     let name = fields[0];
     if let Ok(length) = fields[1].parse::<f32>() {    #10
         println!("{}, {}cm", name, length);           #11
     }
   }
 }

A practical Rust program combines expression-oriented features while processing CSV-like records: iteration, filtering, closures, parsing, and conditional handling appear in one small example. section 1.5

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Defines expression and statement boundaries, then demonstrates conditional, match, function, and loop values without descending into compiler internals.
Examples
Demonstrates conditional and match assignments, value-returning loops, and CSV processing with closures and parsing.
What it assumes
Assumes basic Rust syntax while introducing expression values, implicit returns, conditional branches, and statement distinctions.
What you can do after
Apply expression-based control flow to assign values, return results, process records, and write concise Rust programs.
How it connects
Connects expressions with conditional branching, match expressions, functions, loops, closures, statements, and the unit type.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.