Notes
  • Artificial-Intelligence
    • Introduction
    • Graph Search
    • Constraint Satisfaction Problems
    • Game Playing
    • Decision Networks and Value of Information
    • Reasoning over Time or Space
    • Naive Bayes
    • Probability and Bayes Nets
  • C++
    • Variables and Basic Types
    • Strings, Vectors, and Arrays
    • Classes
  • Compilers
    • Introduction
    • Lexical Analysis
  • Computer-Architecture
    • RISC-V Instruction Formats
    • Single Cycle RISC-V CPU
    • Instructions and Processors in MIPS
    • Dynamic Scheduling
  • Computer-Networking
    • DNS
    • Email
    • File Transfer Protocol (FTP)
    • Principles of Network Applications
    • The Web and HTTP
    • introduction
    • link-layer-reliable-data-transmission
    • network-layer
    • The Sockets Interface
    • Transportation Layer
  • Data-Structures-and-Algorithms
    • Disjoint Sets
    • Priority Queues and Heaps
    • Sort
  • Database-Systems
    • Introduction
    • Modeling
    • Relational Algebra and SQL
    • Database Administration
    • Transaction
    • Files and Indices
    • Query Processing
    • Query Optimization
    • Normalization
    • Data Warehousing and Dimensional Modeling
    • Distributed Databases
    • NoSQL
  • Distributed-ML
    • Distributed ML
    • PyTorch Distributed Training
  • Introduction-to-Computer-Systems
    • X86-64
    • Exception Control Flow
    • Linking
    • Network Programming
  • LeetCode
    • Dynamic Programming
  • Miscellaneous
    • Glibc Malloc
    • 八股总结
    • Python Memory Management
    • QEMU
  • Operating-Systems
    • Cache
    • Deadlocks
    • File Sytem Concepts
    • Interprocess Communication Cases
    • Inter-process Communication Concepts
    • Interprocess Communication Implementation
    • Exceptions
    • Introduction
    • I/O
    • Case Study: Linux Futex (Fast Userspace Mutex)
    • Case Study: Linux Scheduling
    • Case Study: Linux Task Model
    • Memory Management: Mechanisms
    • Memory Management: Strategies
    • Case Study: Pintos Booting
    • Process and Thread
    • Programming: Process and Thread
    • Singals
    • Scheduling
    • Storage Devices
    • Synchronization and Mutual Exclusion
  • Rust
    • collections
    • Fundamental Types
    • Crates and Modules
    • Enumeration
    • Error Handling
    • Expressions
    • generic-types-and-traits
    • Ownership and Moves
    • References
    • Struct
    • Traits and Generics
  • Swift
    • Swift
  • Papers
    • Access-Pattern-of-Remote-Memory
      • Fast RDMA-based Ordered Key-Value Store using Remote Learned Cache
    • Token-Fusion-for-NER
      • AiluRus: A Scalable ViT Framework for Dense Prediction
      • Adaptive Local-then-Global Token Merging for Efficient Semantic Segmentation with Plain Vision Trans
      • Dynamic Token Pruning in Plain Vision Transformers for Semantic Segmentation
      • EViT: Expediting Vision Transformers via Token Reorganizations
      • Which Tokens to Use? Investigating Token Reduction in Vision Transformers
      • Joint Token Pruning and Squeezing (TPS)
      • Learned Token Pruning for Transformers
      • Paper-List
      • SegViT: Semantic Segmentation with Plain Vision Transformers
      • Token Merging: Your ViT But Faster
Powered by GitBook
On this page
  • Declarations
  • if and match
  • if let
  • Loops
  • Control Flow in Loops
  • return Expressions
  • Function and Method Calls
  • Fields and Elements
  • Arithmetic, Bitwise, Comparison, and Logical Operators
  • Type Casts
  • Closures
  1. Rust

Expressions

In C, expressions and statements are different. Expressions have values. Statements don’t.

In Rust, if and match can produce values. Most of the control flow tools in C are statements. In Rust, they are all expressions.

Declarations

You may occasionally see code that seems to redeclare an existing variable, like this:

for line in file.lines() {
    let line = line?;
    ...
}

// equivalent to

for line_result in file.lines() {
    let line = line_result?;
    ...
}

The let declaration creates a new, second variable, of a different type. The type of the first variable line is Result<String, io::Error>. The second line is a String. Its definition supersedes the first’s for the rest of the block. This is called shadowing and is very common in Rust programs.

When an fn is declared inside a block, its scope is the entire block—that is, it can be used throughout the enclosing block. A nested fn cannot access local variables or arguments that happen to be in scope.

if and match

match code {
    0 => println!("OK"),
    1 => println!("Wires Tangled"),
    2 => println!("User Asleep"),
    _ => println!("Unrecognized Error {}", code)
}

All blocks of an if expression must produce values of the same type. Similarly, all arms of a match expression must have the same type.

if let

if let pattern = expr {
    block1
} else {
    block2
}

The given expr either matches the pattern, in which case block1 runs, or doesn’t match, and block2 runs.

Loops

while condition {
  block
}

while let pattern = expr {
  block
}

loop {
  // Use loop to write infinite loops. It executes the block repeatedly forever (or until a break or return is reached or the thread panics).
  block
}

for pattern in iterable {
  block
}

The .. operator produces a range, a simple struct with two fields: start and end. 0..20 is the same as std::ops::Range { start: 0, end: 20 }. Ranges can be used with for loops because Range is an iterable type: it implements the std::iter::IntoIterator trait.

let strings: Vec<String> = error_messages();
for s in strings {                  // each String is moved into s here...
    println!("{}", s);
}                                   // ...and dropped here
println!("{} error(s)", strings.len()); // error: use of moved value

Control Flow in Loops

Within the body of a loop, you can give break an expression, whose value becomes that of the loop:

// Each call to `next_line` returns either `Some(line)`, where
// `line` is a line of input, or `None`, if we've reached the end of
// the input. Return the first line that starts with "answer: ".
// Otherwise, return "answer: nothing".
let answer = loop {
    if let Some(line) = next_line() {
        if line.starts_with("answer: ") {
            break line;
        }
    } else {
        break "answer: nothing";
    }
};

A loop can be labeled with a lifetime. In the following example, 'search: is a label for the outer for loop. Thus, break 'search exits that loop, not the inner loop:

'search:
for room in apartment {
    for spot in room.hiding_spots() {
        if spot.contains(keys) {
            println!("Your keys are {} in the {}.", spot, room);
            break 'search;
        }
    }
}

A break can have both a label and a value expression. Labels can also be used with continue.

return Expressions

return without a value is shorthand for return ().

We used the ? operator to check for errors after calling a function that can fail:

let output = File::create(filename)?;
let output = match File::create(filename) {
    Ok(f) => f,
    Err(err) => return Err(err)
};

Expressions that don’t finish normally are assigned the special type !, and they’re exempt from the rules about types having to match. You can see ! in the function signature of std::process::exit():

fn exit(code: i32) -> !

The ! means that exit() never returns. It’s a divergent function.

You can write divergent functions of your own using the same syntax, and this is perfectly natural in some cases:

fn serve_forever(socket: ServerSocket, handler: ServerHandler) -> ! {
    socket.listen();
    loop {
        let s = socket.accept();
        handler.handle(s);
    }
}

Rust then considers it an error if the function can return normally.

Function and Method Calls

. operator is ease with the types.

Syntax for generic types:

return Vec::<i32>::with_capacity(1000);  // ok, using ::<

let ramp = (0 .. n).collect::<Vec<i32>>();  // ok, using ::<

The symbol ::<...> is affectionately known in the Rust community as the turbofish.

Fields and Elements

ame.black_pawns   // struct field
coords.1           // tuple element
pieces[i]          // array element

Expressions like these three are called lvalues, because they can appear on the left side of an assignment.

Extracting a slice from an array or vector is straightforward:

let second_half = &game_moves[midpoint .. end];

The ..= operator produces end-inclusive (or closed) ranges, which do include the end value:

..= b    // RangeToInclusive { end: b }
a ..= b  // RangeInclusive::new(a, b)

Arithmetic, Bitwise, Comparison, and Logical Operators

Rust uses ! instead of ~ for bitwise NOT.

Bit shifting is always sign-extending on signed integer types and zero-extending on unsigned integer types. Since Rust has unsigned integers, it does not need an unsigned shift operator, like Java’s >>> operator.

Bitwise operations have higher precedence than comparisons, unlike C, so if you write x & BIT != 0, that means (x & BIT) != 0, as you probably intended. This is much more useful than C’s interpretation, x & (BIT != 0), which tests the wrong bit!

Type Casts

Rust does not have C’s increment and decrement operators ++ and --.

Numbers may be cast from any of the built-in numeric types to any other.

Values of type bool or char, or of a C-like enum type, may be cast to any integer type.


Some casts involving unsafe pointer types are also allowed.

  • Values of type &String auto-convert to type &str without a cast.

  • Values of type &Vec<i32> auto-convert to &[i32].

  • Values of type &Box<Chessboard> auto-convert to &Chessboard.

These are called deref coercions, because they apply to types that implement the Deref built-in trait. The purpose of Deref coercion is to make smart pointer types, like Box, behave as much like the underlying value as possible. Using a Box<Chessboard> is mostly just like using a plain Chessboard, thanks to Deref.

Closures

Rust has closures, lightweight function-like values. A closure usually consists of an argument list, given between vertical bars, followed by an expression:

let is_even = |x| x % 2 == 0;
PreviousError HandlingNextgeneric-types-and-traits

Last updated 9 months ago