Fundamental-Types#
There are many, many types of books in the world, which makes good sense, because there are many, many types of people, and everybody wants to read something different. —Lemony Snicke
>
>
Fixed-Width Numeric Types#

// 10_u8.checked_mul(10).expect("数值溢出");
// 100_u8.checked_add(200).expect("");
// let x = 100_u8;
// let y = 100_u8;
// // Do the addition; panic if it overflows.
// let sum = x.checked_add(y).unwrap();
// 超出不报错
500_u16.wrapping_mul(500); // 53392
500_i16.wrapping_mul(500); // -12144
// In bitwise shift operations, the shift distance
// is wrapped to fall within the size of the value.
// So a shift of 17 bits in a 16-bit type is a shift
// of 1.
// assert_eq!(5_i16.wrapping_shl(17), 10);rust

Characters#
assert_eq!('*' as i32, 42);
assert_eq!('ಠ' as u16, 0xca0);
assert_eq!('ಠ' as i8, -0x60); // U+0CA0 truncated to eight bits, signedrustassert_eq!('*'.is_alphabetic(), false);
assert_eq!('β'.is_alphabetic(), true);
assert_eq!('8'.to_digit(10), Some(8));
assert_eq!('ಠ'.len_utf8(), 3);
assert_eq!(std::char::from_digit(2, 10), Some('2'));rustTuples#
let text = "I see the eigenvalue in thine eye";
let (head, tail) = text.split_at(21);
assert_eq!(head, "I see the eigenvalue ");
assert_eq!(tail, "in thine eye");rustlet text = "I see the eigenvalue in thine eye";
let temp = text.split_at(21);
let head = temp.0;
let tail = temp.1;
assert_eq!(head, "I see the eigenvalue ");
assert_eq!(tail, "in thine eye");rustSlices#
let v: Vec<f64> = vec![0.0, 0.707, 1.0, 0.707];
let a: [f64; 4] = [0.0, -0.707, -1.0, -0.707];
let sv: &[f64] = &v;
let sa: &[f64] = &a;rustError: The variable `sv` contains a reference with a non-static lifetime so
can't be persisted. You can prevent this error by making sure that the
variable goes out of scope - i.e. wrapping the code in {}.
[E0597] Error: `a` does not live long enough
╭─[command_23:1:1]
│
2 │ let a: [f64; 4] = [0.0, -0.707, -1.0, -0.707];
│ ┬
│ ╰── binding `a` declared here
│
4 │ let sa: &[f64] = &a;
│ ─┬
│ ╰── borrowed value does not live long enough
│ │
│ ╰── cast requires that `a` is borrowed for `'static`
───╯plaintext
String Literals#
println!("In the room the women come and go,
Singing of Mount Abora");
println!("It was a bright, cold day in April, and \
there were four of us—\
more or less.");
let default_win_install_path = r"C:\Program Files\Gorillas";
println!(r###"
This raw string started with 'r###"'.
Therefore it does not end until we reach a quote mark ('"')
followed immediately by three pound signs ('###'):
"###);rustIn the room the women come and go,
Singing of Mount Abora
It was a bright, cold day in April, and there were four of us—more or less.
This raw string started with 'r###"'.
Therefore it does not end until we reach a quote mark ('"')
followed immediately by three pound signs ('###'):plaintextByte Strings#
let method = b"GET";
assert_eq!(method, &[b'G', b'E', b'T']);rustStrings#
let noodles = "noodles".to_string();
let oodles = &noodles[1..];
let poodles = "ಠ_ಠ";rustlet oodles = &noodles[1..];
let oodles = &noodles[1..];
^^^^^^
The variable `oodles` contains a reference with a non-static lifetime so
can't be persisted. You can prevent this error by making sure that the
variable goes out of scope - i.e. wrapping the code in {}.plaintext
assert_eq!("ಠ_ಠ".len(), 7);
assert_eq!("ಠ_ಠ".chars().count(), 3)rust()plaintext
let error_message = "too many pets".to_string();rustprintln!("{}",error_message)rusttoo many pets
()plaintextformat string#
println!("{}",format!("{}°{:02}′{:02}″N", 24, 5, 23))rust24°05′23″N
()plaintextlet bits = vec!["veni", "vidi", "vici"];rustbits.concat()rust"venividivici"plaintextbits.join(",")rust"veni,vidi,vici"plaintext"ONE".to_lowercase()rust"one"plaintext"peanut".contains("nut")rusttrueplaintext"ಠ_ಠ".replace("ಠ", "■")rust"■_■"plaintextrustOwnership-and-Moves#
Ownership#
{
let point = Box::new((0.625, 0.5)); // point allocated here
let label = format!("{:?}", point); // label allocated here
assert_eq!(label, "(0.625, 0.5)");
}rust()plaintext
struct Person { name: String, birth: i32 }
let mut composers = Vec::new();
composers.push(Person {
name: "Abc".to_string(),
birth: 123,
});
composers.push(Person {
name: "DEF".to_string(),
birth: 444,
});
composers.push(Person {
name: "ASD".to_string(),
birth: 555,
});
for composer in &composers {
println!("{}, born {}", composer.name, composer.birth);
}rustAbc, born 123
DEF, born 444
ASD, born 555
()plaintext
Moves#
let s = vec!["udon".to_string(), "ramen".to_string(), "soba".to_string()];
let t = s;
let u = s;rust[E0382] Error: use of moved value: `s`
╭─[command_4:1:1]
│
1 │ let s = vec!["udon".to_string(), "ramen".to_string(), "soba".to_string()];
│ ┬
│ ╰── move occurs because `s` has type `Vec<String>`, which does not implement the `Copy` trait
2 │ let t = s;
│ ┬│
│ ╰── value moved here
│ │
│ ╰─ help: consider cloning the value if the performance cost is acceptable: `.clone()`
3 │ let u = s;
│ ┬
│ ╰── value used here after move
───╯plaintext
let s = vec!["udon".to_string(), "ramen".to_string(), "soba".to_string()];
let t = s.clone();
let u = s.clone();rustMore Operations That Move#
let mut s = "Govinda".to_string();
s = "Siddhartha".to_string(); // value "Govinda" dropped hererustlet mut s = "Govinda".to_string();
let t = s;
s = "Siddhartha".to_string(); // nothing is dropped hererustMoves and Control Flow#

Moves and Indexed Content#
// Build a vector of the strings "101", "102", ... "105"
let mut v = Vec::new();
for i in 101 .. 106 {
v.push(i.to_string());
}rust()plaintext// Pull out random elements from the vector.
let third = v[2]; // error: Cannot move out of index of Vec
let fifth = v[4]; // here toorust[E0507] Error: cannot move out of index of `Vec<String>`
╭─[command_9:1:1]
│
2 │ let third = v[2]; // error: Cannot move out of index of Vec
│ ┬─┬─
│ ╰───── help: consider borrowing here: `&`
│ │
│ ╰─── move occurs because value has type `String`, which does not implement the `Copy` trait
───╯
[E0507] Error: cannot move out of index of `Vec<String>`
╭─[command_9:1:1]
│
3 │ let fifth = v[4]; // here too
│ ┬─┬─
│ ╰───── help: consider borrowing here: `&`
│ │
│ ╰─── move occurs because value has type `String`, which does not implement the `Copy` trait
───╯plaintext// 1. Pop a value off the end of the vector:
let fifth = v.pop().expect("vector empty!");
assert_eq!(fifth, "105");rust// 2. Move a value out of a given index in the vector,
// and move the last element into its spot:
let second = v.swap_remove(1);
assert_eq!(second, "102");
// 3. Swap in another value for the one we're taking out:
let third = std::mem::replace(&mut v[2], "substitute".to_string());
assert_eq!(third, "103");
// Let's see what's left of our vector.
assert_eq!(v, vec!["101", "104", "substitute"]);ruststruct Person { name: Option<String>, birth: i32 }
let mut composers = Vec::new();
composers.push(Person { name: Some("Palestrina".to_string()),
birth: 1525 });rustlet first_name = composers[0].name;rust[E0507] Error: cannot move out of index of `Vec<Person>`
╭─[command_13:1:1]
│
1 │ let first_name = composers[0].name;
│ ┬───────┬────────
│ ╰────────────────── help: consider borrowing here: `&`
│ │
│ ╰────────── move occurs because value has type `Option<String>`, which does not implement the `Copy` trait
───╯plaintextlet first_name = std::mem::replace(&mut composers[0].name, None);
assert_eq!(first_name, Some("Palestrina".to_string()));
assert_eq!(composers[0].name, None);rustlet first_name = composers[0].name.take();rustCopy Types: The Exception to Moves#
let string1 = "somnambulance".to_string();
let string2 = string1;
let num1: i32 = 36;
let num2 = num1;rust
struct Label { number: u32 }
fn print(l: Label) { println!("STAMP: {}", l.number); }
let l = Label { number: 3 };
print(l);
println!("My label number is: {}", l.number);rust[E0382] Error: borrow of moved value: `l`
╭─[command_17:1:1]
│
3 │ let l = Label { number: 3 };
│ ┬
│ ╰── move occurs because `l` has type `Label`, which does not implement the `Copy` trait
4 │ print(l);
│ ┬
│ ╰── value moved here
5 │ println!("My label number is: {}", l.number);
│ ────┬───
│ ╰───── value borrowed here after move
───╯plaintext#[derive(Copy, Clone)]
struct Label { number: u32 }rust#[derive(Copy, Clone)]
struct StringLabel { name: String }rust[E0204] Error: the trait `Copy` cannot be implemented for this type
╭─[command_19:1:1]
│
1 │ #[derive(Copy, Clone)]
│ ──┬─
│ ╰─── error: the trait `Copy` cannot be implemented for this type
2 │ struct StringLabel { name: String }
│ ──────┬─────
│ ╰─────── this field does not implement `Copy`
───╯plaintextRc and Arc: Shared Ownership#
use std::rc::Rc;
// Rust can infer all these types; written out for clarity
let s: Rc<String> = Rc::new("shirataki".to_string());
let t: Rc<String> = s.clone();
let u: Rc<String> = s.clone();rust
assert!(s.contains("shira"));
assert_eq!(t.find("taki"), Some(5));
println!("{} are quite chewy, almost bouncy, but lack flavor", u);rustshirataki are quite chewy, almost bouncy, but lack flavorplaintexts.push_str(" noodles");rust[E0596] Error: cannot borrow data in an `Rc` as mutable
╭─[command_22:1:1]
│
1 │ s.push_str(" noodles");
│ ┬
│ ╰── cannot borrow as mutable
│
│ Note: You can change an existing variable to mutable like: `let mut x = x;`
───╯plaintext
rustReferences#
Libraries cannot provide new inabilities. —Mark Miller
use std::collections::HashMap;
type Table = HashMap<String, Vec<String>>;rustfn show(table:Table) {
for (artist,works) in table {
println!("works by {}",artist);
for work in works {
println!(" {}",work);
}
}
}rustlet mut table = Table::new();
table.insert("Gesualdo".to_string(),
vec!["many madrigals".to_string(),
"Tenebrae Responsoria".to_string()]);
table.insert("Caravaggio".to_string(),
vec!["The Musicians".to_string(),
"The Calling of St. Matthew".to_string()]);
table.insert("Cellini".to_string(),
vec!["Perseus with the head of Medusa".to_string(),
"a salt cellar".to_string()]);
show(table);rustworks by Gesualdo
many madrigals
Tenebrae Responsoria
works by Caravaggio
The Musicians
The Calling of St. Matthew
works by Cellini
Perseus with the head of Medusa
a salt cellarplaintextfn sort_works(table: &mut Table) {
for (_artist, works) in table {
works.sort();
}
}rustlet mut table = Table::new();
table.insert("Gesualdo".to_string(),
vec!["many madrigals".to_string(),
"Tenebrae Responsoria".to_string()]);
table.insert("Caravaggio".to_string(),
vec!["The Musicians".to_string(),
"The Calling of St. Matthew".to_string()]);
table.insert("Cellini".to_string(),
vec!["Perseus with the head of Medusa".to_string(),
"a salt cellar".to_string()]);
sort_works(&mut table);rustAssigning References#
let x = 10;
let y = 20;
let mut r = &x;
if true { r = &y; }
assert!(*r == 10 || *r == 20);rustError: The variable `r` contains a reference with a non-static lifetime so
can't be persisted. You can prevent this error by making sure that the
variable goes out of scope - i.e. wrapping the code in {}.
Error: The variable `r` contains a reference with a non-static lifetime so
can't be persisted. You can prevent this error by making sure that the
variable goes out of scope - i.e. wrapping the code in {}.plaintext
References to References#
{
struct Point { x: i32, y: i32 }
let point = Point { x: 1000, y: 729 };
let r: &Point = &point;
let rr: &&Point = &r;
let rrr: &&&Point = &rr;
assert_eq!(rrr.y, 729);
}rust()plaintext
Comparing References#
{
let x = 10;
let y = 10;
let rx = &x;
let ry = &y;
let rrx = ℞
let rry = &ry;
assert!(rrx <= rry);
assert!(rrx == rry);
assert!(rx == ry); // their referents are equal
assert!(!std::ptr::eq(rx, ry)); // but occupy different addresses
assert!(rx == rrx); // error: type mismatch: `&i32` vs `&&i32`
assert!(rx == *rrx); // this is okay
}rust[E0277] Error: can't compare `{integer}` with `&{integer}`
╭─[command_19:1:1]
│
13 │ assert!(rx == rrx); // error: type mismatch: `&i32` vs `&&i32`
│ ─┬
│ ╰── no implementation for `{integer} == &{integer}`
────╯plaintextBorrowing a Local Variable#
{
let r;
{
let x = 1;
r = &x;
}
assert_eq!(*r,1);
}rust[E0597] Error: `x` does not live long enough
╭─[command_20:1:1]
│
4 │ let x = 1;
│ ┬
│ ╰── binding `x` declared here
5 │ r = &x;
│ ─┬
│ ╰── borrowed value does not live long enough
6 │ }
│ ┬
│ ╰── `x` dropped here while still borrowed
7 │ assert_eq!(*r,1);
│ ────────┬───────
│ ╰───────── borrow later used here
───╯plaintext

Receiving References as Function Arguments#
// This code has several problems, and doesn't compile.
static mut STASH: &i32;
fn f(p: &i32) { STASH = p; }rustError: free static item without body
╭─[command_21:1:1]
│
2 │ static mut STASH: &i32;
│ ───────────┬──────────┬
│ ╰───────────── error: free static item without body
│ │
│ ╰── help: provide a definition for the static: ` = <expr>;`
───╯plaintextstatic mut STASH: &i32 = &128;
fn f(p: &i32) { // still not good enough
unsafe {
STASH = p;
}
}rustError: lifetime may not live long enough
╭─[command_22:1:1]
│
2 │ fn f(p: &i32) { // still not good enough
│ ┬
│ ╰── let's call the lifetime of this reference `'1`
│
4 │ STASH = p;
│ ────┬────
│ ╰────── assignment requires that `'1` must outlive `'static`
───╯plaintextstatic mut STASH: &i32 = &10;
fn f(p: &'static i32) {
unsafe {
STASH = p;
println!("{}",STASH);
}
}ruststatic WORTH_POINTING_AT: i32 = 1000;
f(&WORTH_POINTING_AT);rust1000plaintext{
unsafe {
println!("{}",STASH);
println!("{}",WORTH_POINTING_AT);
}
}rust10
1000
()plaintextPassing References to Functions#
// This could be written more briefly: fn g(p: &i32),
// but let's write out the lifetimes for now.
fn g<'a>(p: &'a i32) { }
let x = 10;
g(&x);rustfn f(p: &'static i32) { }
let x = 10;
f(&x);
// This fails to compile: the reference &x must not outlive x, but by passing it to f, we
// constrain it to live at least as long as 'static. There’s no way to satisfy everyone here,
// so Rust rejects the code.rustfn f(p: &'static i32) { }
^ warning: unused variable: `p`
unused variable: `p`
help: if this is intentional, prefix it with an underscore
_p
warning: unused variable: `p`
unused variable: `p`
help: if this is intentional, prefix it with an underscore
_p
f(&x);
^^ borrowed value does not live long enough
let x = 10;
^ binding `x` declared here
f(&x);
^^^^^ argument requires that `x` is borrowed for `'static`
`x` does not live long enoughplaintextReturning References#
fn smallest(v: &[i32]) -> &i32 {
let mut s = &v[0];
for r in &v[1..] {
if *r < *s { s = r; }
}
s
}rust// fn smallest<'a>(v: &'a [i32]) -> &'a i32 { }rustlet s;
{
let parabola = [9, 4, 1, 0, 1, 4, 9];
s = smallest(¶bola);
}
assert_eq!(*s, 0);rust[unused_variables] Error: unused variable: `p`
[E0597] Error: `parabola` does not live long enough
╭─[command_42:1:1]
│
3 │ let parabola = [9, 4, 1, 0, 1, 4, 9];
│ ────┬───
│ ╰───── binding `parabola` declared here
4 │ s = smallest(¶bola);
│ ────┬────
│ ╰────── borrowed value does not live long enough
│ │
│ ╰────── cast requires that `parabola` is borrowed for `'static`
5 │ }
│ ┬
│ ╰── `parabola` dropped here while still borrowed
───╯plaintext{
let parabola = [9, 4, 1, 0, 1, 4, 9];
let s = smallest(¶bola);
assert_eq!(*s, 0); // fine: parabola still alive
}rust()plaintextStructs Containing References#
// This does not compile.
struct S {
r: &i32
}
let s;
{
let x = 10;
s = S { r: &x };
}
assert_eq!(*s.r, 10); // bad: reads from dropped `x`rust[E0106] Error: missing lifetime specifier
╭─[command_44:1:1]
│
3 │ r: &i32
│ ┬
│ ╰── expected named lifetime parameter
───╯plaintextstruct S<'a> {
r: &'a i32
}
{
let s;
{
let x = 10;
s = S { r: &x };
}
assert_eq!(*s.r, 10);
}rust[unused_variables] Error: unused variable: `p`
[E0597] Error: `x` does not live long enough
╭─[command_49:1:1]
│
7 │ let x = 10;
│ ┬
│ ╰── binding `x` declared here
8 │ s = S { r: &x };
│ ─┬
│ ╰── borrowed value does not live long enough
9 │ }
│ ┬
│ ╰── `x` dropped here while still borrowed
10 │ assert_eq!(*s.r, 10);
│ ──────────┬─────────
│ ╰─────────── borrow later used here
────╯plaintextDistinct Lifetime Parameters#
struct S<'a> {
x: &'a i32,
y: &'a i32
}rust{
let x = 10;
let r;
{
let y = 20;
{
let s = S { x: &x, y: &y };
r = s.x;
}
}
println!("{}", r);
}rust[unused_variables] Error: unused variable: `p`
[E0597] Error: `y` does not live long enough
╭─[command_56:1:1]
│
5 │ let y = 20;
│ ┬
│ ╰── binding `y` declared here
│
7 │ let s = S { x: &x, y: &y };
│ ─┬
│ ╰── borrowed value does not live long enough
│
10 │ }
│ ┬
│ ╰── `y` dropped here while still borrowed
11 │ println!("{}", r);
│ ┬
│ ╰── borrow later used here
────╯plaintextstruct S<'a, 'b> {
x: &'a i32,
y: &'b i32
}rust{
let x = 10;
let r;
{
let y = 20;
{
let s = S { x: &x, y: &y };
r = s.x;
}
}
println!("{}", r);
}rust10
()plaintextfn f<'a>(r: &'a i32, s: &'a i32) -> &'a i32 { r } // perhaps too tightrustfn f<'a, 'b>(r: &'a i32, s: &'b i32) -> &'a i32 { r } // looserrustfn f<b>(r: &'a i32, s: &'b i32) -> &'a i32 { r }rust[E0261] Error: use of undeclared lifetime name `'a`
╭─[command_64:1:1]
│
1 │ fn f<b>(r: &'a i32, s: &'b i32) -> &'a i32 { r }
│ │ ─┬
│ ╰────────── help: consider introducing lifetime `'a` here: `'a, `
│ │
│ ╰── undeclared lifetime
───╯
[E0261] Error: use of undeclared lifetime name `'b`
╭─[command_64:1:1]
│
1 │ fn f<b>(r: &'a i32, s: &'b i32) -> &'a i32 { r }
│ │ ─┬
│ ╰────────────────────── help: consider introducing lifetime `'b` here: `'b, `
│ │
│ ╰── undeclared lifetime
───╯
[E0261] Error: use of undeclared lifetime name `'a`
╭─[command_64:1:1]
│
1 │ fn f<b>(r: &'a i32, s: &'b i32) -> &'a i32 { r }
│ │ ─┬
│ ╰────────────────────────────────── help: consider introducing lifetime `'a` here: `'a, `
│ │
│ ╰── undeclared lifetime
───╯
[non_camel_case_types] Error: type parameter `b` should have an upper camel case name
╭─[command_64:1:1]
│
1 │ fn f<b>(r: &'a i32, s: &'b i32) -> &'a i32 { r }
│ ┬
│ ╰── warning: type parameter `b` should have an upper camel case name
│ │
│ ╰── help: convert the identifier to upper camel case: `B`
───╯plaintextOmitting Lifetime Parameters#
struct S<'a, 'b> {
x: &'a i32,
y: &'b i32
}rustfn sum_r_xy(r: &i32, s: S) -> i32 {
r + s.x + s.y
}rust// fn sum_r_xy<'a, 'b, 'c>(r: &'a i32, s: S<'b, 'c>) -> i32rustfn first_third(point: &[i32; 3]) -> (&i32, &i32) {
(&point[0], &point[2])
}rust// fn first_third<'a>(point: &'a [i32; 3]) -> (&'a i32, &'a i32)ruststruct StringTable {
elements: Vec<String>,
}
impl StringTable {
fn find_by_prefix(&self,prefix:&str) -> Option<&String> {
for i in 0..self.elements.len() {
if self.elements[i].starts_with(prefix) {
return Some(&self.elements[i]);
}
}
None
}
}
// fn find_by_prefix<'a, 'b>(&'a self, prefix: &'b str) -> Option<&'a String>rustSharing Versus Mutation#
let v = vec![4, 8, 19, 27, 34, 10];
let r = &v;
let aside = v; // move vector to aside
r[0]; // bad: uses `v`, which is now uninitializedrust[unused_variables] Error: unused variable: `s`
[unused_variables] Error: unused variable: `p`
Error: The variable `r` contains a reference with a non-static lifetime so
can't be persisted. You can prevent this error by making sure that the
variable goes out of scope - i.e. wrapping the code in {}.plaintext
let v = vec![4, 8, 19, 27, 34, 10];
{
let r = &v;
r[0]; // ok: vector is still there
}
let aside = v;rustfn extend(vec: &mut Vec<f64>, slice: &[f64]) {
for elt in slice {
vec.push(*elt);
}
}rustlet mut wave = Vec::new();
let head = vec![0.0, 1.0];
let tail = [0.0, -1.0];
extend(&mut wave, &head); // extend wave with another vector
extend(&mut wave, &tail); // extend wave with an array
assert_eq!(wave, vec![0.0, 1.0, 0.0, -1.0]);rustextend(&mut wave, &wave);
assert_eq!(wave, vec![0.0, 1.0, 0.0, -1.0,
0.0, 1.0, 0.0, -1.0])rust[unused_variables] Error: unused variable: `s`
[unused_variables] Error: unused variable: `p`
[E0502] Error: cannot borrow `wave` as immutable because it is also borrowed as mutable
╭─[command_83:1:1]
│
1 │ extend(&mut wave, &wave);
│ ───┬── ────┬──── ──┬──
│ ╰───────────────────── mutable borrow later used by call
│ │ │
│ ╰───────────── mutable borrow occurs here
│ │
│ ╰──── immutable borrow occurs here
───╯plaintext

Taking Arms Against a Sea of Objects#

ruststruct-enums-patterns#
Long ago, when shepherds wanted to see if two herds of sheep were isomorphic, they would look for an explicit isomorphism. —John C. Baez and James Dolan, “
Named-Field Structs#
// A rectangle of eight-bit grayscale pixels.
struct GrayscaleMap {
pixels: Vec<u8>,
size: (usize, usize)
}rustlet width = 1024;
let height = 576;
let image = GrayscaleMap {
pixels: vec![0; width * height],
size: (width, height)
};rustimagerust[E0277] Error: `GrayscaleMap` doesn't implement `Debug`plaintext/// A rectangle of eight-bit grayscale pixels.
// 模块外访问
pub struct GrayscaleMap {
pub pixels: Vec<u8>,
pub size: (usize, usize)
}rustTuple-Like Structs#
#[derive(Copy, Clone, Debug)]
struct Bounds(usize, usize);rustlet image_bounds = Bounds(1024, 768);
image_boundsrustThe type of the variable image was redefined, so was lost.
Bounds(1024, 768)plaintextUnit-Like Structs#
struct A;
let a=A;rustStruct Layout 内存布局#

Defining Methods with impl#
/// A first-in, first-out queue of characters.
pub struct Queue {
older: Vec<char>, // older elements, eldest last.
younger: Vec<char> // younger elements, youngest last.
}rustimpl Queue {
pub fn push(&mut self,c: char) {
self.younger.push(c);
}
pub fn pop(&mut self) -> Option<char> {
if self.older.is_empty() {
if self.younger.is_empty() {
return None;
}
use std::mem::swap;
swap(&mut self.older,&mut self.younger);
self.older.reverse();
}
self.older.pop()
}
}rustlet mut q = Queue { older: Vec::new(), younger: Vec::new() };
q.push('0');
q.push('1');
assert_eq!(q.pop(), Some('0'));
q.push('∞');
assert_eq!(q.pop(), Some('1'));
assert_eq!(q.pop(), Some('∞'));
assert_eq!(q.pop(), None);rustimpl Queue {
pub fn is_empty(&self) -> bool {
self.older.is_empty() && self.younger.is_empty()
}
}rustassert!(q.is_empty());
q.push('☉');
assert!(!q.is_empty());rustimpl Queue {
pub fn split(self) -> (Vec<char>, Vec<char>) {
(self.older, self.younger)
}
}rustlet mut q = Queue { older: Vec::new(), younger: Vec::new() };rustq.push('P');
q.push('D');
assert_eq!(q.pop(), Some('P'));
q.push('X');
let (older, younger) = q.split();
// q is now uninitialized.
assert_eq!(older, vec!['D']);
assert_eq!(younger, vec!['X'])
rust()plaintextqrust[E0425] Error: cannot find value `q` in this scope
╭─[command_23:1:1]
│
1 │ q
│ ┬
│ ╰── error: cannot find value `q` in this scope
│ │
│ ╰── help: a unit struct with a similar name exists: `A`
───╯plaintextimpl Queue {
fn new() -> Queue {
Queue { older: Vec::new(), younger: Vec::new() }
}
}rustlet mut bq = Box::new(Queue::new());
bq.push('A')rust()plaintextuse std::rc::Rc;ruststruct Node {
tag: String,
children: Vec<Rc<Node>>
}rustimpl Node {
fn new(tag: &str) ->Node {
Node {
tag: tag.to_string(),
children: vec![],
}
}
}rustimpl Node {
fn append_to(self: Rc<Self>, parent: &mut Node) {
parent.children.push(self);
}
}rustlet shared_node = Rc::new(Node::new("first"));rustpub struct Vector2 {
x: f32,
y: f32,
}rustimpl Vector2 {
const ZERO: Vector2 = Vector2 { x: 0.0, y: 0.0 };
const UNIT: Vector2 = Vector2 { x: 1.0, y: 0.0 };
}rustlet scaled = Vector2::UNIT.x;rustGeneric Structs#
pub struct TheQueue<T> {
older: Vec<T>,
younger: Vec<T>
}rustimpl<T> TheQueue<T> {
pub fn new() -> TheQueue<T> {
TheQueue { older: Vec::new(), younger: Vec::new() }
}
pub fn push(&mut self, t: T) {
self.younger.push(t);
}
pub fn is_empty(&self) -> bool {
self.older.is_empty() && self.younger.is_empty()
}
}rustimpl TheQueue<f64> {
fn sum(&self) -> f64 {
0_f64
}
}rustlet mut q = TheQueue::<char>::new();rustq.push('a');rustStructs with Lifetime Parameters#
struct Extrema<'elt> {
greatest: &'elt i32,
least: &'elt i32,
}rustfn find_extrema<'s>(slice: &'s [i32]) -> Extrema<'s> {
let mut greatest = &slice[0];
let mut least = &slice[0];
for i in 1..slice.len() {
if slice[i] < *least { least = &slice[i]; }
if slice[i] > *greatest { greatest = &slice[i]; }
}
Extrema { greatest, least }
}rustDeriving Common Traits for Struct Types#
#[derive(Copy, Clone, Debug, PartialEq)]
struct Point {
x: f64,
y: f64
}rust{
use std::cell::RefCell;
let ref_cell: RefCell<String> = RefCell::new("hello".to_string());
let r = ref_cell.borrow();
let count = r.len();
assert_eq!(count,5);
let mut w = ref_cell.borrow_mut();
w.push_str("world");
}rustthread '<unnamed>' panicked at src/lib.rs:247:22:
already borrowed: BorrowMutError
stack backtrace:
0: rust_begin_unwind
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:597:5
1: core::panicking::panic_fmt
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:72:14
2: core::cell::panic_already_borrowed
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/cell.rs:762:5
3: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
4: run_user_code_39
5: evcxr::runtime::Runtime::run_loop
6: evcxr::runtime::runtime_hook
7: evcxr_jupyter::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.plaintextEnums and Patterns#
use std::cmp::Ordering;
fn compare(a: i32,b: i32) -> Ordering {
if a > b {
Ordering::Greater
} else if a < b {
Ordering::Less
} else {
Ordering::Equal
}
}rustenum HttpStatus {
Ok = 200,
NotModified = 304,
NotFound = 404,
}rustuse std::mem::size_of;
assert_eq!(size_of::<Ordering>(), 1);
assert_eq!(size_of::<HttpStatus>(), 2); // 404 doesn't fit in a u8rust#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum TimeUnit {
Seconds, Minutes, Hours, Days, Months, Years,
}rustimpl TimeUnit {
/// Return the plural noun for this time unit.
fn plural(self) -> &'static str {
match self {
TimeUnit::Seconds => "seconds",
TimeUnit::Minutes => "minutes",
TimeUnit::Hours => "hours",
TimeUnit::Days => "days",
TimeUnit::Months => "months",
TimeUnit::Years => "years",
}
}
/// Return the singular noun for this time unit.
fn singular(self) -> &'static str {
self.plural().trim_end_matches('s')
}
}rustEnums in Memory#

Patterns#
enum RoughTime {
InThePast(TimeUnit, u32),
JustNow,
InTheFuture(TimeUnit, u32),
}rustfn rough_time_to_english(rt: RoughTime) -> String {
match rt {
RoughTime::InThePast(units, count) =>
format!("{} {} ago", count, units.plural()),
RoughTime::JustNow =>
format!("just now"),
RoughTime::InTheFuture(units, count) =>
format!("{} {} from now", count, units.plural()),
}
}rust
fn greet_people(names: &[&str]) {
match names {
[] => { println!("Hello, nobody.") },
[a] => { println!("Hello, {}.", a) },
[a, b] => { println!("Hello, {} and {}.", a, b) },
[a, .., b] => { println!("Hello, everyone from {} to {}.", a, b) }
}
}rust

// An ordered collection of `T`s.
enum BinaryTree<T> {
Empty,
NonEmpty(Box<TreeNode<T>>),
}
// A part of a BinaryTree.
struct TreeNode<T> {
element: T,
left: BinaryTree<T>,
right: BinaryTree<T>,
}rustimpl <T: Ord> BinaryTree<T> {
fn add(&mut self,value :T) {
match *self {
BinaryTree::Empty => {
*self = BinaryTree::NonEmpty(Box::new(
TreeNode {
element: value,
left: BinaryTree::Empty,
right: BinaryTree::Empty,
}
))
},
BinaryTree::NonEmpty(ref mut node) => {
if value <= node.element {
node.left.add(value);
} else {
node.right.add(value);
}
}
}
}
}rustStructs#
LISP programmers know the value of everything, but the cost of nothing. —Alan Perlis, epigram
>
>
Error Handling#
I knew if I stayed around long enough, something like this would happen. —George Bernard Shaw on dying
use std::error::Error;
use std::io::{Write,stderr};
fn print_error(mut err: &dyn Error) {
let _ = writeln!(stderr(),"error: {}",err);
while let Some(source) = err.source() {
let _ = writeln!(stderr(),"cased by :{}",source);
err = source;
}
}rustlet weather = match get_weather(hometown) {
Ok(success_value) => success_value,
Err(err) => return Err(err)
};rustCrates and Modules#

mod spores {
use cells::{Cell, Gene};
/// A cell made by an adult fern. It disperses on the wind as part of
/// the fern life cycle. A spore grows into a prothallus -- a whole
/// separate organism, up to 5mm across -- which produces the zygote
/// that grows into a new fern. (Plant sex is complicated.)
pub struct Spore {
...
}
/// Simulate the production of a spore by meiosis.
pub fn produce_spore(factory: &mut Sporangium) -> Spore {
...
}
/// Extract the genes in a particular spore.
pub(crate) fn genes(spore: &Spore) -> Vec<Gene> {
...
}
/// Mix genes to prepare for meiosis (part of interphase).
fn recombine(parent: &mut Cell) {
...
}
...
}rust

bin#

Attributes#

Test#
#[test]
fn trig_works() {
use std::f64::consts::PI;
assert!(roughly_equal(PI.sin(), 0.0));
}
```rust
#[cfg(test)] // 仅当run test时才会include 这个模块
// include this module only when testing
mod tests {
fn roughly_equal(a: f64, b: f64) -> bool {
(a - b).abs() < 1e-6
}
#[test]
fn trig_works() {
use std::f64::consts::PI;
assert!(roughly_equal(PI.sin(), 0.0));
}
}rustDocumentation#

Package Versions#

rustInput and Output#

use std::io::{self, Read, Write, ErrorKind};
const DEFAULT_BUF_SIZE: usize = 8 * 1024;
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W)
-> io::Result<u64>
where R: Read,W: Write
{
let mut buf = [0; DEFAULT_BUF_SIZE];
let mut writern = 0;
loop {
let len = match reader.read(&mut buf) {
Ok(0) => return Ok(writern),
Ok(len) => len,
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
};
writer.write_all(&buf[..len])?;
writern += len as u64;
}
}rust
use std::io;
use std::io::prelude::*;
fn grep(target: &str) -> io::Result<()> {
let stdin = io::stdin();
for line_result in stdin.lock().lines() {
let line = line_result?;
if line.contains(target) {
println!("{}",line);
}
}
Ok(())
}rustfn grep<R>(target: &str, reader: R) -> io::Result<()>
where R: BufRead
{
for line_result in reader.lines() {
let line = line_result?;
if line.contains(target) {
println!("{}", line);
}
}
Ok(())
}rust// let stdin = io::stdin();
// grep(&target, stdin.lock())?; // ok
// let f = File::open(file)?;
// grep(&target, BufReader::new(f))?; // also orustuse std::fs::OpenOptions;
let log = OpenOptions::new()
.append(true)
.open("server.log").unwrap_err();
let file = OpenOptions::new()
.write(true)
.create_new(true)
.open("new_file.log").unwrap_err();rustthread '<unnamed>' panicked at src/lib.rs:138:27:
called `Result::unwrap_err()` on an `Ok` value: File { fd: 3, path: "/home/realcpf/Documents/rustRepos/rust-prog-2021/new_file.log", read: false, write: true }
stack backtrace:
0: rust_begin_unwind
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:597:5
1: core::panicking::panic_fmt
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:72:14
2: core::result::unwrap_failed
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/result.rs:1652:5
3: <unknown>
4: <unknown>
5: evcxr::runtime::Runtime::run_loop
6: evcxr::runtime::runtime_hook
7: evcxr_jupyter::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.plaintextuse std::process::{Command, Stdio};
let mut child =
Command::new("grep")
.arg("-e")
.arg("a.*e.*i.*o.*u")
.stdin(Stdio::piped())
.spawn()?;
let mut to_child = child.stdin.take().unwrap();
for word in my_words {
writeln!(to_child, "{}", word)?;
}
drop(to_child); // close grep's stdin, so it will exit
child.wait()?;rust[E0425] Error: cannot find value `my_words` in this scope
╭─[command_12:1:1]
│
9 │ for word in my_words {
│ ────┬───
│ ╰───── not found in this scope
───╯plaintext
use std::path::Path;
let home_dir = Path::new("/home/realcpf");rustassert_eq!(home_dir.parent(),Some(Path::new("/home")));rustuse std::ffi::OsStr;
assert_eq!(Path::new("/home/fwolfe/program.txt").file_name(),
Some(OsStr::new("program.txt")));rustlet path1 = Path::new("/usr/share/dict");
assert_eq!(path1.join("words"),
Path::new("/usr/share/dict/words"));rustlet file = Path::new("/home/jimb/calendars/calendar-18x18.pdf");
assert_eq!(file.ancestors().collect::<Vec<_>>(),
vec![Path::new("/home/jimb/calendars/calendar-18x18.pdf"),
Path::new("/home/jimb/calendars"),
Path::new("/home/jimb"),
Path::new("/home"),
Path::new("/")])rust()plaintext

use std::fs;
use std::io;
use std::path::Path;
/// Copy wha tever is at `src` to the target path `dst`.
fn copy_to(src: &Path, src_type: &fs::FileType, dst: &Path)
-> io::Result<()>
{
if src_type.is_file() {
fs::copy(src, dst)?;
} else if src_type.is_dir() {
copy_dir_to(src, dst)?;
} else {
return Err(io::Error::new(io::ErrorKind::Other,
format!("don't know how to copy: {}",
src.display())));
}
Ok(())
}
// Copy the existing directory `src` to the target path `dst`.
fn copy_dir_to(src: &Path, dst: &Path) -> io::Result<()> {
if !dst.is_dir() {
fs::create_dir(dst)?;
}
for entry_result in src.read_dir()? {
let entry = entry_result?;
let file_type = entry.file_type()?;
copy_to(&entry.path(), &file_type, &dst.join(entry.file_name()))?;
}
Ok(())
}rust#[cfg(unix)]
use std::os::unix::fs::symlink;
/// Stub implementation of `symlink` for platforms that don't provide it.
#[cfg(not(unix))]
fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, _dst: Q)
-> std::io::Result<()>
{
Err(io::Error::new(io::ErrorKind::Other,
format!("can't copy symbolic link: {}",
src.as_ref().display())))
}rustuse std::net::TcpListener;
use std::io;
use std::thread::spawn;
/// Accept connections forever, spawning a thread for each one.
fn echo_main(addr: &str) -> io::Result<()> {
let listener = TcpListener::bind(addr)?;
println!("listening on {}", addr);
loop {
// Wait for a client to connect.
let (mut stream, addr) = listener.accept()?;
println!("connection received from {}", addr);
// Spawn a thread to handle this client.
let mut write_stream = stream.try_clone()?;
spawn(move || {
// Echo everything we receive from `stream` back to it.
io::copy(&mut stream, &mut write_stream)
.expect("error in client thread: ");
println!("connection closed");
});
}
}
fn main() {
echo_main("127.0.0.1:17007").expect("error: ");
}rustuse std::error::Error;
use std::io;
fn http_get_main(url: &str) -> Result<(), Box<dyn Error>> {
// Send the HTTP request and get a response.
let mut response = reqwest::blocking::get(url)?;
if !response.status().is_success() {
Err(format!("{}", response.status()))?;
}
// Read the response body and write it to stdout.
let stdout = io::stdout();
io::copy(&mut response, &mut stdout.lock())?;
Ok(())
}
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() != 2 {
eprintln!("usage: http-get URL");
return;
}
if let Err(err) = http_get_main(&args[1]) {
eprintln!("error: {}", err);
}
}
```rustrustStrings and Text#

assert_eq!("うどん: udon".as_bytes(),
&[0xe3, 0x81, 0x86, //う
0xe3, 0x81, 0xa9, //ど
0xe3, 0x82, 0x93, //ん
0x3a, 0x20, 0x75, 0x64, 0x6f, 0x6e // : udon
]);rustassert_eq!(" ערבטוב ".chars().next(), Some('ע'));rustthread '<unnamed>' panicked at src/lib.rs:6:1:
assertion `left == right` failed
left: Some(' ')
right: Some('ע')
stack backtrace:
0: rust_begin_unwind
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:597:5
1: core::panicking::panic_fmt
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:72:14
2: core::panicking::assert_failed_inner
3: <unknown>
4: <unknown>
5: evcxr::runtime::Runtime::run_loop
6: evcxr::runtime::runtime_hook
7: evcxr_jupyter::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.plaintextassert_eq!("カニ".chars().next(), Some('カ'))rust()plaintext

assert!(32u8.is_ascii_whitespace());
assert!(b'9'.is_ascii_digit())rust()plaintext// char::is_ascii_whitespace函数实现了许多Web标准通用的空格定义,
// 而char::is_whitespace遵循Unicode标准。
let line_tab = '\u{000b}'; // 'line tab', AKA 'vertical tab'
assert_eq!(line_tab.is_whitespace(), true);
assert_eq!(line_tab.is_ascii_whitespace(), false)rust()plaintextassert_eq!('F'.to_digit(16), Some(15));
assert_eq!(std::char::from_digit(15, 16), Some('f'));
assert!(char::is_digit('f', 16));rustlet mut upper = 's'.to_uppercase();
assert_eq!(upper.next(), Some('S'));
assert_eq!(upper.next(), None);rust// The uppercase form of the German letter "sharp S" is "SS":
let mut upper = 'ß'.to_uppercase();
assert_eq!(upper.next(), Some('S'));
assert_eq!(upper.next(), Some('S'));
assert_eq!(upper.next(), None);rust// Unicode says to lowercase Turkish dotted capital 'İ' to 'i'
// followed by `'\u{307}'`, COMBINING DOT ABOVE, so that a
// subsequent conversion back to uppercase preserves the dot.
let ch = 'İ'; // `'\u{130}'`
let mut lower = ch.to_lowercase();
assert_eq!(lower.next(), Some('i'));
assert_eq!(lower.next(), Some('\u{307}'));
assert_eq!(lower.next(), None)rust()plaintextassert_eq!('B' as u32, 66);
assert_eq!('饂' as u8, 66); // upper bits truncated
assert_eq!('二' as i8, -116); // samerustassert_eq!(char::from(66), 'B');
assert_eq!(std::char::from_u32(0x9942), Some('饂'));
assert_eq!(std::char::from_u32(0xd800), None); // reserved for UTF-16rust
let spacey = "man hat tan";
let spaceless: String =
spacey.chars().filter(|c| !c.is_whitespace()).collect();
assert_eq!(spaceless, "manhattan");rustlet full = "bookkeeping";
assert_eq!(&full[..4], "book");
assert_eq!(&full[5..], "eeping");
assert_eq!(&full[2..4], "ok");
assert_eq!(full[..].len(), 11);
assert_eq!(full[5..].contains("boo"), false)rust()plaintextlet parenthesized = "Rust (饂)";
assert_eq!(parenthesized[6..].chars().next(), Some('饂'));rustlet mut also_spaceless = "con".to_string();
also_spaceless.extend("tri but ion".split_whitespace());
assert_eq!(also_spaceless, "contribution");rustuse std::fmt::Write;
let mut letter = String::new();
writeln!(letter, "Whose {} these are I think I know", "rutabagas")?;
writeln!(letter, "His house is in the village though;")?;
assert_eq!(letter, "Whose rutabagas these are I think I know\n\
His house is in the village though;\n");rustlet left = "partners".to_string();
let mut right = "crime".to_string();
assert_eq!(left + " in " + &right, "partners in crime");
right += " doesn't pay";
assert_eq!(right, "crime doesn't pay")rust()plaintext// 返回给定字节索引范围内的迭代器,并在删除迭代器后删除字符。范围后的字符向前面移动
let mut choco = "chocolate".to_string();
assert_eq!(choco.drain(3..6).collect::<String>(), "col");
assert_eq!(choco, "choate");rustlet mut beverage = "a piña colada".to_string();
beverage.replace_range(2..7, "kahlua"); // 'ñ' is two bytes!
assert_eq!(beverage, "a kahlua colada");rustlet haystack = "One fine day, in the middle of the night";
assert_eq!(haystack.find(','), Some(12));
assert_eq!(haystack.find("night"), Some(35));
assert_eq!(haystack.find(char::is_whitespace), Some(3));rustassert_eq!("## Elephants"
.trim_start_matches(|ch: char| ch == '#' || ch.is_whitespace()),
"Elephants");rustlet code = "\t function noodle() { ";
assert_eq!(code.trim_start_matches([' ', '\t'].as_ref()),
"function noodle() { ");
// Shorter equivalent: &[' ', '\t'][..]rustassert!("2017".starts_with(char::is_numeric));rustlet quip = "We also know there are known unknowns";
assert_eq!(quip.find("know"), Some(8));
assert_eq!(quip.rfind("know"), Some(31));
assert_eq!(quip.find("ya know"), None);
assert_eq!(quip.rfind(char::is_uppercase), Some(0));rustassert_eq!("The only thing we have to fear is fear itself"
.replace("fear", "spin"),
"The only thing we have to spin is spin itself");
assert_eq!("`Borrow` and `BorrowMut`"
.replace(|ch:char| !ch.is_alphanumeric(), ""),
"BorrowandBorrowMut");rust
assert_eq!("élan".char_indices().collect::<Vec<_>>(),
vec![(0, 'é'), // has a two-byte UTF-8 encoding
(2, 'l'),
(3, 'a'),
(4, 'n')]);rustassert_eq!("élan".bytes().collect::<Vec<_>>(),
vec![195, 169, b'l', b'a', b'n']);rust// The ':' characters are separators here. Note the final "".
assert_eq!("jimb:1000:Jim Blandy:".split(':').collect::<Vec<_>>(),
vec!["jimb", "1000", "Jim Blandy", ""]);
// The '\n' characters are terminators here.
assert_eq!("127.0.0.1 localhost\n\
127.0.0.1 www.reddit.com\n"
.split_terminator('\n').collect::<Vec<_>>(),
vec!["127.0.0.1 localhost",
"127.0.0.1 www.reddit.com"]);
// Note, no final ""!rustlet poem = "This is just to say\n\
I have eaten\n\
the plums\n\
again\n";
assert_eq!(poem.split_whitespace().collect::<Vec<_>>(),
vec!["This", "is", "just", "to", "say",
"I", "have", "eaten", "the", "plums",
"again"]);rustassert_eq!("\t*.rs ".trim(), "*.rs");
assert_eq!("\t*.rs ".trim_start(), "*.rs ");
assert_eq!("\t*.rs ".trim_end(), "\t*.rs");rustassert_eq!("001990".trim_start_matches('0'), "1990");rustuse std::str::FromStr;
assert_eq!(usize::from_str("3628800"), Ok(3628800));
assert_eq!(f64::from_str("128.5625"), Ok(128.5625));
assert_eq!(bool::from_str("true"), Ok(true));
assert!(f64::from_str("not a float at all").is_err());
assert!(bool::from_str("TRUE").is_err());rustassert_eq!(char::from_str("é"), Ok('é'));
assert!(char::from_str("abcdefg").is_err());rustuse std::net::IpAddr;
let address = IpAddr::from_str("fe80::0000:3ea9:f4ff:fe34:7a50")?;
assert_eq!(address,
IpAddr::from([0xfe80, 0, 0, 0, 0x3ea9, 0xf4ff, 0xfe34, 0x7a50]));rustlet address = "fe80::0000:3ea9:f4ff:fe34:7a50".parse::<IpAddr>().unwrap();rustassert_eq!(format!("{}, wow", "doge"), "doge, wow");
assert_eq!(format!("{}", true), "true");
assert_eq!(format!("({:.3}, {:.3})", 0.5, f64::sqrt(3.0)/2.0),
"(0.500, 0.866)");
// Using `address` from above.
let formatted_addr: String = format!("{}", address);
assert_eq!(formatted_addr, "fe80::3ea9:f4ff:fe34:7a50");rustProducing Text from UTF-8 Data#
let good_utf8: Vec<u8> = vec![0xe9, 0x8c, 0x86];
assert_eq!(String::from_utf8(good_utf8).ok(), Some("錆".to_string()));
let bad_utf8: Vec<u8> = vec![0x9f, 0xf0, 0xa6, 0x80];
let result = String::from_utf8(bad_utf8);
assert!(result.is_err());
// Since String::from_utf8 failed, it didn't consume the original
// vector, and the error value hands it back to us unharmed.
assert_eq!(result.unwrap_err().into_bytes(),
vec![0x9f, 0xf0, 0xa6, 0x80])rust()plaintextfn get_name() -> String {
std::env::var("USER") // Windows uses "USERNAME"
.unwrap_or("whoever you are".to_string())
}
println!("Greetings, {}!", get_name())rustGreetings, realcpf!
()plaintextuse std::borrow::Cow;
fn get_name() -> Cow<'static ,str> {
std::env::var("USER")
.map(|v|Cow::Owned(v))
.unwrap_or(Cow::Borrowed("whover you are"))
}
println!("Greetings, {}!", get_name())rustGreetings, realcpf!
()plaintextFormatting Values#
println!("{:.3}μs: relocated {} at {:#x} to {:#x}, {} bytes",
0.84391, "object",
140737488346304_usize, 6299664_usize, 64);rust0.844μs: relocated object at 0x7fffffffdcc0 to 0x602010, 64 bytesplaintext
assert_eq!(format!("{{a, c}} ⊂ {{a, b, c}}"),
"{a, c} ⊂ {a, b, c}");rustFormatting Text Values#

assert_eq!(format!("{:4}", "th\u{e9}"), "th\u{e9} ");
assert_eq!(format!("{:4}", "the\u{301}"), "the\u{301}");rustFormatting Numbers#

use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("Portland", (45.5237606,-122.6819273));
map.insert("Taipei", (25.0375167, 121.5637));
println!("{:?}", map);rust{"Taipei": (25.0375167, 121.5637), "Portland": (45.5237606, -122.6819273)}plaintextprintln!("ordinary: {:02?}", [9, 15, 240]);
println!("hex: {:02x?}", [9, 15, 240]);rustordinary: [09, 15, 240]
hex: [09, 0f, f0]plaintext#[derive(Copy, Clone, Debug)]
struct Complex { re: f64, im: f64 }
let third = Complex { re: -0.5, im: f64::sqrt(0.75) };
println!("{:?}", third)rustComplex { re: -0.5, im: 0.8660254037844386 }
()plaintextFormatting Pointers for Debugging#
use std::rc::Rc;
let original = Rc::new("mazurka".to_string());
let cloned = original.clone();
let impostor = Rc::new("mazurka".to_string());
println!("text: {}, {}, {}", original, cloned, impostor);
println!("pointers: {:p}, {:p}, {:p}", original, cloned, impostor);rusttext: mazurka, mazurka, mazurka
pointers: 0x55ab5c90f080, 0x55ab5c90f080, 0x55ab5c917540plaintextassert_eq!(format!("{1},{0},{2}", "zeroth", "first", "second"),
"first,zeroth,second");
assert_eq!(format!("{2:#06x},{1:b},{0:=>10}", "first", 10, 100),
"0x0064,1010,=====first");rustformat!("{description:.<25}{quantity:2} @ {price:5.2}",
price=3.25,
quantity=3,
description="Maple Turmeric Latte")rust"Maple Turmeric Latte..... 3 @ 3.25"plaintextformat!("{mode} {2} {} {}",
"people", "eater", "purple", mode="flying")rust"flying purple people eater"plaintext
use std::fmt;
impl fmt::Display for Complex {
fn fmt(&self, dest: &mut fmt::Formatter) -> fmt::Result {
let im_sign = if self.im < 0.0 { '-' } else { '+' };
write!(dest, "{} {} {}i", self.re, im_sign, f64::abs(self.im))
}
}rustlet one_twenty = Complex { re: -0.5, im: 0.866 };
assert_eq!(format!("{}", one_twenty),
"-0.5 + 0.866i");
let two_forty = Complex { re: -0.5, im: -0.866 };
assert_eq!(format!("{}", two_forty),
"-0.5 - 0.866i");rustrustFundamental-Types#
There are many, many types of books in the world, which makes good sense, because there are many, many types of people, and everybody wants to read something different. —Lemony Snicke
>
>
Fixed-Width Numeric Types#

// 10_u8.checked_mul(10).expect("数值溢出");
// 100_u8.checked_add(200).expect("");
// let x = 100_u8;
// let y = 100_u8;
// // Do the addition; panic if it overflows.
// let sum = x.checked_add(y).unwrap();
// 超出不报错
500_u16.wrapping_mul(500); // 53392
500_i16.wrapping_mul(500); // -12144
// In bitwise shift operations, the shift distance
// is wrapped to fall within the size of the value.
// So a shift of 17 bits in a 16-bit type is a shift
// of 1.
// assert_eq!(5_i16.wrapping_shl(17), 10);rust

Characters#
assert_eq!('*' as i32, 42);
assert_eq!('ಠ' as u16, 0xca0);
assert_eq!('ಠ' as i8, -0x60); // U+0CA0 truncated to eight bits, signedrustassert_eq!('*'.is_alphabetic(), false);
assert_eq!('β'.is_alphabetic(), true);
assert_eq!('8'.to_digit(10), Some(8));
assert_eq!('ಠ'.len_utf8(), 3);
assert_eq!(std::char::from_digit(2, 10), Some('2'));rustTuples#
let text = "I see the eigenvalue in thine eye";
let (head, tail) = text.split_at(21);
assert_eq!(head, "I see the eigenvalue ");
assert_eq!(tail, "in thine eye");rustlet text = "I see the eigenvalue in thine eye";
let temp = text.split_at(21);
let head = temp.0;
let tail = temp.1;
assert_eq!(head, "I see the eigenvalue ");
assert_eq!(tail, "in thine eye");rustSlices#
let v: Vec<f64> = vec![0.0, 0.707, 1.0, 0.707];
let a: [f64; 4] = [0.0, -0.707, -1.0, -0.707];
let sv: &[f64] = &v;
let sa: &[f64] = &a;rustError: The variable `sv` contains a reference with a non-static lifetime so
can't be persisted. You can prevent this error by making sure that the
variable goes out of scope - i.e. wrapping the code in {}.
[E0597] Error: `a` does not live long enough
╭─[command_23:1:1]
│
2 │ let a: [f64; 4] = [0.0, -0.707, -1.0, -0.707];
│ ┬
│ ╰── binding `a` declared here
│
4 │ let sa: &[f64] = &a;
│ ─┬
│ ╰── borrowed value does not live long enough
│ │
│ ╰── cast requires that `a` is borrowed for `'static`
───╯plaintext
String Literals#
println!("In the room the women come and go,
Singing of Mount Abora");
println!("It was a bright, cold day in April, and \
there were four of us—\
more or less.");
let default_win_install_path = r"C:\Program Files\Gorillas";
println!(r###"
This raw string started with 'r###"'.
Therefore it does not end until we reach a quote mark ('"')
followed immediately by three pound signs ('###'):
"###);rustIn the room the women come and go,
Singing of Mount Abora
It was a bright, cold day in April, and there were four of us—more or less.
This raw string started with 'r###"'.
Therefore it does not end until we reach a quote mark ('"')
followed immediately by three pound signs ('###'):plaintextByte Strings#
let method = b"GET";
assert_eq!(method, &[b'G', b'E', b'T']);rustStrings#
let noodles = "noodles".to_string();
let oodles = &noodles[1..];
let poodles = "ಠ_ಠ";rustlet oodles = &noodles[1..];
let oodles = &noodles[1..];
^^^^^^
The variable `oodles` contains a reference with a non-static lifetime so
can't be persisted. You can prevent this error by making sure that the
variable goes out of scope - i.e. wrapping the code in {}.plaintext
assert_eq!("ಠ_ಠ".len(), 7);
assert_eq!("ಠ_ಠ".chars().count(), 3)rust()plaintext
let error_message = "too many pets".to_string();rustprintln!("{}",error_message)rusttoo many pets
()plaintextformat string#
println!("{}",format!("{}°{:02}′{:02}″N", 24, 5, 23))rust24°05′23″N
()plaintextlet bits = vec!["veni", "vidi", "vici"];rustbits.concat()rust"venividivici"plaintextbits.join(",")rust"veni,vidi,vici"plaintext"ONE".to_lowercase()rust"one"plaintext"peanut".contains("nut")rusttrueplaintext"ಠ_ಠ".replace("ಠ", "■")rust"■_■"plaintextrustIterator#
// You should usually use HashSet, but its iteration order is
// nondeterministic, so BTreeSet works better in examples.
use std::collections::BTreeSet;
let mut favorites = BTreeSet::new();
favorites.insert("Lucy in the Sky With Diamonds".to_string());
favorites.insert("Liebesträume No. 3".to_string());
let mut it = favorites.into_iter();
assert_eq!(it.next(), Some("Liebesträume No. 3".to_string()));
assert_eq!(it.next(), Some("Lucy in the Sky With Diamonds".to_string()));
assert_eq!(it.next(), None);rustuse rand::random; // In Cargo.toml dependencies: rand = "0.7"
use std::iter::from_fn;
// Generate the lengths of 1000 random line segments whose endpoints
// are uniformly distributed across the interval [0, 1]. (This isn't a
// distribution you're going to find in the `rand_distr` crate, but
// it's easy to make yourself.)
let lengths: Vec<f64> =
from_fn(|| Some((random::<f64>() - random::<f64>()).abs()))
.take(1000)
.collect();rust[E0432] Error: unresolved import `rand`plaintextfn fibonacci() -> impl Iterator<Item = usize> {
let mut state = (0,1);
std::iter::from_fn(move || {
state = (state.1,state.0 + state.1);
Some(state.0)
})
}rustassert_eq!(fibonacci().take(8).collect::<Vec<_>>(),
vec![1, 1, 2, 3, 5, 8, 13, 21])rust()plaintextdrain Methods#
use std::iter::FromIterator;
let mut outer = "Earth".to_string();
let inner = String::from_iter(outer.drain(1..4));
assert_eq!(outer, "Eh");
assert_eq!(inner, "art")rust()plaintextIterator Sources#

map and filter#
{
let text = " ponies \n giraffes\niguanas \nsquid".to_string();
let v: Vec<&str> = text.lines()
.map(str::trim)
.collect();
assert_eq!(v, ["ponies", "giraffes", "iguanas", "squid"]);
}rust()plaintext{
let text = " ponies \n giraffes\niguanas \nsquid".to_string();
let v: Vec<&str> = text.lines()
.map(str::trim)
.filter(|s| *s != "iguanas")
.collect();
assert_eq!(v, ["ponies", "giraffes", "squid"]);
}rust()plaintextfilter_map and flat_map#
use std::str::FromStr;
let text = "1\nfrond .25 289\n3.1415 estuary\n";
for number in text.split_whitespace()
.filter_map(|w| f64::from_str(w).ok()){
println!("{:4.2}",number.sqrt());
}rust1.00
0.50
17.00
1.77
()plaintextuse std::collections::HashMap;
let mut major_cities = HashMap::new();
major_cities.insert("Japan", vec!["Tokyo", "Kyoto"]);
major_cities.insert("The United States", vec!["Portland", "Nashville"]);
major_cities.insert("Brazil", vec!["São Paulo", "Brasília"]);
major_cities.insert("Kenya", vec!["Nairobi", "Mombasa"]);
major_cities.insert("The Netherlands", vec!["Amsterdam", "Utrecht"]);
let countries = ["Japan", "Brazil", "Kenya"];
for &city in countries.iter().flat_map(|country| &major_cities[country]) {
println!("{}", city);
}rustTokyo
Kyoto
São Paulo
Brasília
Nairobi
Mombasa
()plaintextflatten#
use std::collections::BTreeMap;
// A table mapping cities to their parks: each value is a vector.
let mut parks = BTreeMap::new();
parks.insert("Portland", vec!["Mt. Tabor Park", "Forest Park"]);
parks.insert("Kyoto", vec!["Tadasu-no-Mori Forest", "Maruyama Koen"]);
parks.insert("Nashville", vec!["Percy Warner Park", "Dragon Park"]);rustuse std::collections::BTreeMap;
// A table mapping cities to their parks: each value is a vector.
let mut parks = BTreeMap::new();
parks.insert("Portland", vec!["Mt. Tabor Park", "Forest Park"]);
parks.insert("Kyoto", vec!["Tadasu-no-Mori Forest", "Maruyama Koen"]);
parks.insert("Nashville", vec!["Percy Warner Park", "Dragon Park"]);
// Build a vector of all parks. `values` gives us an iterator producing
// vectors, and then `flatten` produces each vector's elements in turn.
let all_parks: Vec<_> = parks.values().flatten().cloned().collect();
assert_eq!(all_parks,
vec!["Tadasu-no-Mori Forest", "Maruyama Koen", "Percy Warner Park",
"Dragon Park", "Mt. Tabor Park", "Forest Park"]);rusttake and take_while#
let message = "To: jimb\r\n\
From: superego <editor@oreilly.com>\r\n\
\r\n\
Did you get any writing done today?\r\n\
When will you stop wasting time plotting fractals?\r\n";
for header in message.lines().take_while(|l| !l.is_empty()) {
println!("{}" , header);
}rustTo: jimb
From: superego <editor@oreilly.com>
()plaintextskip and skip_while#
for body in message.lines()
.skip_while(|l| !l.is_empty())
.skip(1) {
println!("{}" , body);
}rustDid you get any writing done today?
When will you stop wasting time plotting fractals?
()plaintextpeekable#
use std::iter::Peekable;
fn parse_number<I>(tokens: &mut Peekable<I>) -> u32
where I:Iterator<Item = char>{
let mut n = 0;
loop {
match tokens.peek() {
Some(r) if r.is_digit(10) => {
n = n * 10 + r.to_digit(10).unwrap();
}
_ => return n
}
tokens.next();
}
}rustlet mut chars = "226153980,1766319049".chars().peekable();
assert_eq!(parse_number(&mut chars), 226153980);
// Look, `parse_number` didn't consume the comma! So we will.
assert_eq!(chars.next(), Some(','));
assert_eq!(parse_number(&mut chars), 1766319049);
assert_eq!(chars.next(), None);rustfuse#
struct Flaky(bool);
impl Iterator for Flaky {
type Item = &'static str;
fn next(&mut self) -> Option<Self::Item> {
if self.0 {
self.0 = false;
Some("totally the last item")
} else {
self.0 = true; // D'oh!
None
}
}
}rustlet mut flaky = Flaky(true);
assert_eq!(flaky.next(), Some("totally the last item"));
assert_eq!(flaky.next(), None);
assert_eq!(flaky.next(), Some("totally the last item"));
let mut not_flaky = Flaky(true).fuse();
assert_eq!(not_flaky.next(), Some("totally the last item"));
assert_eq!(not_flaky.next(), None);
assert_eq!(not_flaky.next(), None);rustReversible Iterators and rev#
{
let bee_parts = ["head", "thorax", "abdomen"];
let mut iter = bee_parts.iter();
assert_eq!(iter.next(), Some(&"head"));
assert_eq!(iter.next_back(), Some(&"abdomen"));
assert_eq!(iter.next(), Some(&"thorax"));
assert_eq!(iter.next_back(), None);
assert_eq!(iter.next(), None);
}rust()plaintext// fn rev(self) -> impl Iterator<Item=Self>
// where Self: Sized + DoubleEndedIterator;rust{
let meals = ["breakfast", "lunch", "dinner"];
let mut iter = meals.iter().rev();
assert_eq!(iter.next(), Some(&"dinner"));
assert_eq!(iter.next(), Some(&"lunch"));
assert_eq!(iter.next(), Some(&"breakfast"));
assert_eq!(iter.next(), None);
}rust()plaintextinspect#
let upper_case: String = "große".chars()
.inspect(|c| println!("before: {:?}", c))
.flat_map(|c| c.to_uppercase())
.inspect(|c| println!(" after: {:?}", c))
.collect();
assert_eq!(upper_case, "GROSSE");rustbefore: 'g'
after: 'G'
before: 'r'
after: 'R'
before: 'o'
after: 'O'
before: 'ß'
after: 'S'
after: 'S'
before: 'e'
after: 'E'plaintextchain#
let v: Vec<i32> = (1..4).chain(vec![20, 30, 40]).collect();
assert_eq!(v, [1, 2, 3, 20, 30, 40]);rustlet v: Vec<i32> = (1..4).chain(vec![20, 30, 40]).rev().collect();
assert_eq!(v, [40, 30, 20, 3, 2, 1]);rustenumerate#
let vlist = vec!['A','B','C','D'];
for (i,c) in vlist.into_iter().enumerate() {
println!("{}--{}",i,c);
}rust0--A
1--B
2--C
3--D
()plaintextzip#
let v:Vec<_> = (0..).zip("ABCD".chars()).collect();
assert_eq!(v, vec![(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D')]);rustuse std::iter::repeat;
let endings = vec!["once", "twice", "chicken soup with rice"];
let rhyme: Vec<_> = repeat("going")
.zip(endings)
.collect();
assert_eq!(rhyme, vec![("going", "once"),
("going", "twice"),
("going", "chicken soup with rice")]);rustby_ref#
let message = "To: jimb\r\n\
From: id\r\n\
\r\n\
Oooooh, donuts!!\r\n";
let mut lines = message.lines();
println!("Headers:");
for header in lines.by_ref().take_while(|l| !l.is_empty()) {
println!("{}" , header);
}
println!("\nBody:");
for body in lines {
println!("{}" , body);
}rustHeaders:
To: jimb
From: id
Body:
Oooooh, donuts!!
()plaintextcloned, copied#
let a = ['1', '2', '3', '∞'];
assert_eq!(a.iter().next(), Some(&'1'));
assert_eq!(a.iter().cloned().next(), Some('1'));rustcycle#
{
let dirs = ["North", "East", "South", "West"];
let mut spin = dirs.iter().cycle();
assert_eq!(spin.next(), Some(&"North"));
assert_eq!(spin.next(), Some(&"East"));
assert_eq!(spin.next(), Some(&"South"));
assert_eq!(spin.next(), Some(&"West"));
assert_eq!(spin.next(), Some(&"North"));
assert_eq!(spin.next(), Some(&"East"))
}rust()plaintextuse std::iter::{once, repeat};
{
let fizzes = repeat("").take(2).chain(once("fizz")).cycle();
let buzzes = repeat("").take(4).chain(once("buzz")).cycle();
let fizzes_buzzes = fizzes.zip(buzzes);
let fizz_buzz = (1..100).zip(fizzes_buzzes)
.map(|tuple|
match tuple {
(i, ("", "")) => i.to_string(),
(_, (fizz, buzz)) => format!("{}{}", fizz, buzz)
});
for line in fizz_buzz {
println!("{}", line);
}
}rust1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
16
17
fizz
19
buzz
fizz
22
23
fizz
buzz
26
fizz
28
29
fizzbuzz
31
32
fizz
34
buzz
fizz
37
38
fizz
buzz
41
()
fizz
43
44
fizzbuzz
46
47
fizz
49
buzz
fizz
52
53
fizz
buzz
56
fizz
58
59
fizzbuzz
61
62
fizz
64
buzz
fizz
67
68
fizz
buzz
71
fizz
73
74
fizzbuzz
76
77
fizz
79
buzz
fizz
82
83
fizz
buzz
86
fizz
88
89
fizzbuzz
91
92
fizz
94
buzz
fizz
97
98
fizzplaintextSimple Accumulation: count, sum, product#
use std::cmp::Ordering;
fn cmp(lhs: &f64,rhs:&f64) -> Ordering {
lhs.partial_cmp(rhs).unwrap()
}
let numbers = [1.0, 4.0, 2.0];
assert_eq!(numbers.iter().copied().max_by(cmp), Some(4.0));
assert_eq!(numbers.iter().copied().min_by(cmp), Some(1.0));
let numbers = [1.0, 4.0, std::f64::NAN, 2.0];
assert_eq!(numbers.iter().copied().max_by(cmp), Some(4.0)); // panicsrustthread '<unnamed>' panicked at src/lib.rs:8:26:
called `Option::unwrap()` on a `None` value
stack backtrace:
0: rust_begin_unwind
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:597:5
1: core::panicking::panic_fmt
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:72:14
2: core::panicking::panic
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:127:5
3: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
4: run_user_code_29
5: evcxr::runtime::Runtime::run_loop
6: evcxr::runtime::runtime_hook
7: evcxr_jupyter::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.plaintextmax_by_key, min_by_key#
use std::collections::HashMap;
let mut populations = HashMap::new();
populations.insert("Portland", 583_776);
populations.insert("Fossil", 449);
populations.insert("Greenhorn", 2);
populations.insert("Boring", 7_762);
populations.insert("The Dalles", 15_340);
assert_eq!(populations.iter().max_by_key(|&(_name, pop)| pop),
Some((&"Portland", &583_776)));
assert_eq!(populations.iter().min_by_key(|&(_name, pop)| pop),
Some((&"Greenhorn", &2)));rustComparing Item Sequences#
let packed = "Helen of Troy";
let spaced = "Helen of Troy";
let obscure = "Helen of Sandusky"; // nice person, just not famous
assert!(packed != spaced);
assert!(packed.split_whitespace().eq(spaced.split_whitespace()));
// This is true because ' ' < 'o'.
assert!(spaced < obscure);
// This is true because 'Troy' > 'Sandusky'.
assert!(spaced.split_whitespace().gt(obscure.split_whitespace()));rustthread '<unnamed>' panicked at src/lib.rs:178:1:
assertion failed: packed != spaced
stack backtrace:
0: rust_begin_unwind
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:597:5
1: core::panicking::panic_fmt
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:72:14
2: core::panicking::panic
at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:127:5
3: <unknown>
4: <unknown>
5: evcxr::runtime::Runtime::run_loop
6: evcxr::runtime::runtime_hook
7: evcxr_jupyter::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.plaintextany and all#
let id = "Iterator";
assert!( id.chars().any(char::is_uppercase));
assert!(!id.chars().all(char::is_uppercase));rustposition, rposition, and ExactSizeIterator#
let text = “Xerxes”; assert_eq!(text.chars().position(|c| c == ‘e’), Some(1)); assert_eq!(text.chars().position(|c| c == ‘z’), None); let bytes = b”Xerxes”; assert_eq!(bytes.iter().rposition(|&c| c == b’e’), Some(4)); assert_eq!(bytes.iter().rposition(|&c| c == b’X’), Some(0));
fold and rfold#
let a = [5, 6, 7, 8, 9, 10];
assert_eq!(a.iter().fold(0, |n, _| n+1), 6); // count
assert_eq!(a.iter().fold(0, |n, i| n+i), 45); // sum
assert_eq!(a.iter().fold(1, |n, i| n*i), 151200); // produc
// max
assert_eq!(a.iter().cloned().fold(i32::min_value(), std::cmp::max),
10);rustlet a = ["Pack", "my", "box", "with",
"five", "dozen", "liquor", "jugs"];
// See also: the `join` method on slices, which won't
// give you that extra space at the end.
let pangram = a.iter()
.fold(String::new(), |s, w| s + w + " ");
assert_eq!(pangram, "Pack my box with five dozen liquor jugs ");rustlet weird_pangram = a.iter()
.rfold(String::new(), |s, w| s + w + " ");
assert_eq!(weird_pangram, "jugs liquor dozen five with box my Pack ");rusttry_fold and try_rfold#
rustThe nth method takes an index n, skips that many items from the iterator, and
returns the next item, or None if the sequence ends before that point. Calling .nth(0)
is equivalent to .next()plaintext第nth方法采用索引n,从迭代器中跳过那么多项,并返回下一项,如果序列在该点之前结束,则返回无。调用. nth(0)等价于.next()plaintextlet mut squares = (0..10).map(|i| i*i);
assert_eq!(squares.nth(4), Some(16));
assert_eq!(squares.nth(0), Some(25));
assert_eq!(squares.nth(6), None);rustThe variable `squares` has type `std::iter::Map<std::ops::Range<i32>, impl Fn(i32) -> i32>` which cannot be persisted.
You might be able to fix this by creating a `Box<dyn YourType>`. e.g.
let v: Box<dyn core::fmt::Debug> = Box::new(foo());
Alternatively, you can prevent evcxr from attempting to persist
the variable by wrapping your code in braces.plaintextlast#
let squares = (0..10).map(|i| i*i);
assert_eq!(squares.last(), Some(81));rustThe variable `squares` has type `std::iter::Map<std::ops::Range<i32>, impl Fn(i32) -> i32>` which cannot be persisted.
You might be able to fix this by creating a `Box<dyn YourType>`. e.g.
let v: Box<dyn core::fmt::Debug> = Box::new(foo());
Alternatively, you can prevent evcxr from attempting to persist
the variable by wrapping your code in braces.plaintextfind, rfind, and find_map#
assert_eq!(populations.iter().find(|&(_name, &pop)| pop > 1_000_000),
None);
assert_eq!(populations.iter().find(|&(_name, &pop)| pop > 500_000),
Some((&"Portland", &583_776)));rustlet big_city_with_volcano_park = populations.iter()
.find_map(|(&city, _)| {
if let Some(park) = find_volcano_park(city, &parks) {
// find_map returns this value, so our caller knows
// *which* park we found.
return Some((city, park.name));
}
// Reject this item, and continue the search.
None
});
assert_eq!(big_city_with_volcano_park,
Some(("Portland", "Mt. Tabor Park")));rust[E0425] Error: cannot find function `find_volcano_park` in this scope
╭─[command_50:1:1]
│
3 │ if let Some(park) = find_volcano_park(city, &parks) {
│ ────────┬────────
│ ╰────────── not found in this scope
───╯plaintextBuilding Collections: collect and FromIterator#
let args: Vec<String> = std::env::args().collect();rustuse std::collections::{HashSet, BTreeSet, LinkedList, HashMap, BTreeMap};
let args: HashSet<String> = std::env::args().collect();
let args: BTreeSet<String> = std::env::args().collect();
let args: LinkedList<String> = std::env::args().collect();
// Collecting a map requires (key, value) pairs, so for this example,
// zip the sequence of strings with a sequence of integers.
let args: HashMap<String, usize> = std::env::args().zip(0..).collect();
let args: BTreeMap<String, usize> = std::env::args().zip(0..).collect();rustThe Extend Trait#
let mut v: Vec<i32> = (0..5).map(|i| 1 << i).collect();
v.extend(&[31, 57, 99, 163]);
assert_eq!(v, &[1, 2, 4, 8, 16, 31, 57, 99, 163]);rustpartition#
let things = ["doorknob", "mushroom", "noodle", "giraffe", "grapefruit"];rust// odd-numbered letter.
let (living, nonliving): (Vec<&str>, Vec<&str>)
= things.iter().partition(|name| name.as_bytes()[0] & 1 != 0);
assert_eq!(living, vec!["mushroom", "giraffe", "grapefruit"]);
assert_eq!(nonliving, vec!["doorknob", "noodle"]);rustfor_each and try_for_each#
["doves", "hens", "birds"].iter()
.zip(["turtle", "french", "calling"].iter())
.zip(2..5)
.rev()
.map(|((item, kind), quantity)| {
format!("{} {} {}", quantity, kind, item)
})
.for_each(|gift| {
println!("You have received: {}", gift);
});rustYou have received: 4 calling birds
You have received: 3 french hens
You have received: 2 turtle dovesplaintextfor gift in ["doves", "hens", "birds"].iter()
.zip(["turtle", "french", "calling"].iter())
.zip(2..5)
.rev()
.map(|((item, kind), quantity)| {
format!("{} {} {}", quantity, kind, item)
})
{
println!("You have received: {}", gift);
}rustYou have received: 4 calling birds
You have received: 3 french hens
You have received: 2 turtle doves
()plaintextrustMacro#

macro_rules! bad_assert_eq {
($left:expr, $right:expr) => ({
match ($left, $right) {
(left_val, right_val) => {
if !(left_val == right_val) {
panic!("assertion failed" /* ... */);
}
}
}
});
}rustlet s= "a rose".to_string();
bad_assert_eq!(s,"a rose");
println!("{}",s)rust[E0382] Error: borrow of moved value: `s`
╭─[command_3:1:1]
│
1 │ let s= "a rose".to_string();
│ ┬
│ ╰── move occurs because `s` has type `String`, which does not implement the `Copy` trait
2 │ bad_assert_eq!(s,"a rose");
│ ┬│
│ ╰── value moved here
│ │
│ ╰─ help: consider cloning the value if the performance cost is acceptable: `.clone()`
3 │ println!("{}",s)
│ ┬
│ ╰── value borrowed here after move
───╯plaintext
println!(stringify!("hello"))rust"hello"
()plaintextprintln!(env!("USER"))rustrealcpf
()plaintextconst TEXT : &str = include_str!("/home/realcpf/Documents/rustRepos/rust-prog-2021/hello.txt");
println!("{}",TEXT);rusthello worldplaintextuse std::collections::HashMap;
#[derive(Clone, PartialEq, Debug)]
enum Json {
Null,
Boolean(bool),
Number(f64),
String(String),
Array(Vec<Json>),
Object(Box<HashMap<String, Json>>)
}rustlet students = Json::Array(vec![
Json::Object(Box::new(vec![
("name".to_string(), Json::String("Jim Blandy".to_string())),
("class_of".to_string(), Json::Number(1926.0)),
("major".to_string(), Json::String("Tibetan throat singing".to_string()))
].into_iter().collect())),
Json::Object(Box::new(vec![
("name".to_string(), Json::String("Jason Orendorff".to_string())),
("class_of".to_string(), Json::Number(1702.0)),
("major".to_string(), Json::String("Knots".to_string()))
].into_iter().collect()))
]);rustmacro_rules! json {
(null) => {
Json::Null
};
([ $( $element:expr ),*]) => {
Json:Array(vec![ $( $element ),*])
};
}rustassert_eq!(json!(null),Json::Null)rust()plaintextlet mm = json!(
[
{
"a":3.33
}
]
);
let hand_coded_value =
Json::Array(vec![
Json::Object(Box::new(vec![
("pitch".to_string(), Json::Number(440.0))
].into_iter().collect()))
]);
assert_eq!(mm,hand_coded_value)rustError: expected one of `.`, `;`, `?`, `}`, or an operator, found `:`
╭─[command_15:1:1]
│
4 │ "a":3.33
│ ┬
│ ╰── expected one of `.`, `;`, `?`, `}`, or an operator
───╯
Error: path separator must be a double colon
[unused_macros] Error: unused macro definition: `bad_assert_eq`plaintext
macro_rules! json {
(null) => {
Json::Null
};
([ $( $element:tt ),* ]) => {
Json::Array(...)
};
({ $( $key:tt : $value:tt ),* }) => {
Json::Object(...)
};
($other:tt) => {
... // TODO: Return Number, String, or Boolean
};
}rustmacro_rules! impl_from_num_for_json {
( $( $t:ident )* ) => {
$(
impl From<$t> for Json {
fn from(n: $t) -> Json {
Json::Number(n as f64)
}
}
)*
};
}rustimpl_from_num_for_json!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128
usize isize f32 f64);rustmacro_rules! json {
(null) => {
Json::Null
};
([ $( $element:tt ),* ]) => {
Json::Array(vec![ $( json!($element) ),* ])
};
({ $( $key:tt : $value:tt ),* }) => {
Json::Object(Box::new(vec![
$( ($key.to_string(), json!($value)) ),*
].into_iter().collect()))
};
( $other:tt ) => {
Json::from($other) // Handle Boolean/number/string
};
}rustlet width = 4.0;
let desc =
json!({
"width": width,
"height": (width * 9.0 / 4.0)
});rust[unused_macros] Error: unused macro definition: `bad_assert_eq`
[unused_macros] Error: unused macro definition: `impl_from_num_for_json`
[E0308] Error: mismatched types
╭─[command_20:1:1]
│
3 │ ╭─▶ json!({
4 │ │ "width": width,
│ │ ──┬──
│ │ ╰──── expected `Json`, found floating-point number
┆ ┆
6 │ ├─▶ });
│ │
│ ╰──────── arguments to this function are incorrect
│
│ Note: note: associated function defined here
───╯
[E0308] Error: mismatched types
╭─[command_20:1:1]
│
3 │ ╭─▶ json!({
┆ ┆
5 │ │ "height": (width * 9.0 / 4.0)
│ │ ─────────┬─────────
│ │ ╰─────────── expected `Json`, found floating-point number
6 │ ├─▶ });
│ │
│ ╰──────── arguments to this function are incorrect
│
│ Note: note: associated function defined here
───╯plaintextrustCollections#

// Create an empty vector
let mut numbers: Vec<i32> = vec![];
// Create a vector with given contents
let words = vec!["step", "on", "no", "pets"];
let mut buffer = vec![0u8; 1024]; // 1024 zeroed-out bytesrust
let lines=vec![];
let numbers = vec![];
// Get a reference to an element
let first_line = &lines[0];
// Get a copy of an element
let fifth_number = numbers[4]; // requires Copy
let second_line = lines[1].clone(); // requires Clone
// Get a reference to a slice
let my_ref = &buffer[4..12];
// Get a copy of a slice
let my_copy = buffer[4..12].to_vec(); // requires Clonerust[E0282] Error: type annotations needed for `&T`
╭─[command_5:1:1]
│
4 │ let first_line = &lines[0];
│ ─────┬────│
│ ╰────── error: type annotations needed for `&T`
│ │
│ ╰─ help: consider giving `first_line` an explicit type, where the placeholders `_` are specified: `: &T`
│
7 │ let second_line = lines[1].clone(); // requires Clone
│ ────┬───
│ ╰───── type must be known at this point
───╯plaintextlet slice = [0, 1, 2, 3];
if let Some(item) = slice.first() {
println!("we got {}",item);
}
assert_eq!(slice.get(2), Some(&2));
assert_eq!(slice.get(4), None);rustwe got 0plaintextlet mut slice = [0, 1, 2, 3];
{
let last = slice.last_mut().unwrap();
assert_eq!(*last,3);
*last = 99;
}
assert_eq!(slice,[0,1,2,99]);rustlet v = [1, 2, 3, 4, 5, 6, 7, 8, 9];
assert_eq!(v.to_vec(),
vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
assert_eq!(v[0..6].to_vec(),
vec![1, 2, 3, 4, 5, 6]);rustuse std::collections::HashSet;
let mut byte_vec = b"Misssssssissippi".to_vec();
byte_vec.dedup();
assert_eq!(&byte_vec, b"Misisipi");
let mut byte_vec = b"Misssssssissippi".to_vec();
let mut seen = HashSet::new();
byte_vec.retain(|r| seen.insert(*r));
assert_eq!(&byte_vec, b"Misp");rustassert_eq!([[1, 2], [3, 4], [5, 6]].concat(),
vec![1, 2, 3, 4, 5, 6]);
assert_eq!([[1, 2], [3, 4], [5, 6]].join(&0),
vec![1, 2, 0, 3, 4, 0, 5, 6]);rust{
let v = vec![0, 1, 2, 3];
let i = 1;
let j = 2;
let a = &v[i];
let b = &v[j];
let mid = v.len() / 2;
let front_half = &v[..mid];
let back_half = &v[mid..];
}rust()plaintext{
let mut v = vec![0, 1, 2, 3];
let i = 1;
let j = 2;
let a = &mut v[i];
let b = &mut v[j]; // error: cannot borrow `v` as mutable
// more than once at a time
*a = 6; // references `a` and `b` get used here,
*b = 7; // so their lifetimes must overlap
}rust[E0499] Error: cannot borrow `v` as mutable more than once at a time
╭─[command_19:1:1]
│
5 │ let a = &mut v[i];
│ ┬
│ ╰── first mutable borrow occurs here
6 │ let b = &mut v[j]; // error: cannot borrow `v` as mutable
│ ┬
│ ╰── second mutable borrow occurs here
│
8 │ *a = 6; // references `a` and `b` get used here,
│ ───┬──
│ ╰──── first borrow later used here
───╯plaintext

assert_eq!([1, 2, 3, 4].starts_with(&[1, 2]), true);
assert_eq!([1, 2, 3, 4].starts_with(&[2, 3]), false);
assert_eq!([1, 2, 3, 4].ends_with(&[3, 4]), true);rustuse std::collections::VecDeque;
let v = VecDeque::from(vec![1, 2, 3, 4]);rustuse std::collections::binary_heap::PeekMut;
use std::collections::BinaryHeap;
{
let mut heap = BinaryHeap::from(vec![2, 3, 8, 6, 9, 5, 4]);
if let Some(top) = heap.peek_mut() {
if *top > 10 {
PeekMut::pop(top);
}
}
}rust[E0597] Error: `heap` does not live long enough
╭─[command_28:1:1]
│
6 │ let mut heap = BinaryHeap::from(vec![2, 3, 8, 6, 9, 5, 4]);
│ ────┬───
│ ╰───── binding `heap` declared here
7 │ if let Some(top) = heap.peek_mut() {
│ ──┬────┬───────
│ ╰────────────── borrowed value does not live long enough
│ │
│ ╰───────── a temporary with access to the borrow is created here ...
│
11 │ }
│ │
│ ╰─ help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped: `;`
│
13 │ }
│ ┬
│ ╰── `heap` dropped here while still borrowed
────╯plaintextuse std::collections::HashMap;
let mut vote_counts: HashMap<String, usize> = HashMap::new();
vote_counts.insert(String::from("a"),1);
let ballots = vec![String::from("a")];
for name in ballots {
let count = vote_counts.entry(name).or_insert(0);
*count += 1;
}rust()plaintextlet s1 = "hello".to_string();
let s2 = "hello".to_string();
println!("{:p}", &s1 as &str); // 0x7f8b32060008
println!("{:p}", &s2 as &str); // 0x7f8b32060010rust0x55ae0bc7af70
0x55ae0bc7e270plaintextuse std::hash::{Hash, Hasher, BuildHasher};
fn compute_hash<B, T>(builder: &B, value: &T) -> u64
where B: BuildHasher, T: Hash
{
let mut hasher = builder.build_hasher(); // 1. start the algorithm
value.hash(&mut hasher); // 2. feed it data
hasher.finish() // 3. finish, producing a u64
}rustrustConcurrency#

use std::thread;
thread::spawn(||{
let curr = thread::current();
let name = curr.name().unwrap_or("wrong").to_string();
println!("hello in thread {}",name);
})rustJoinHandle { .. }plaintextuse std::{fs, thread};
use std::sync::mpsc;
let (sender, receiver) = mpsc::channel();
let handle = thread::spawn(move || {
for filename in documents {
let text = fs::read_to_string(filename)?;
if sender.send(text).is_err() {
break;
}
}
Ok(())
});rust[E0425] Error: cannot find value `documents` in this scope
╭─[command_10:1:1]
│
5 │ for filename in documents {
│ ────┬────
│ ╰────── not found in this scope
───╯plaintextuse std::thread;
use std::rc::Rc;
fn main() {
let rc1 = Rc::new("ouch".to_string());
let rc2 = rc1.clone();
thread::spawn(move || { // error
rc2.clone();
});
rc1.clone();
}
Rust refuses to compile it, giving a detailed error message:
error[E0277]: `Rc<String>` cannot be sent between threads safely
--> concurrency_send_rc.rs:10:5
|
10 | thread::spawn(move || { // error
| ^^^^^ `Rc<String>` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `Rc<String>`
= note: required because it appears within the type `[closure@...]`
= note: required by `std::thread::spawnrustuse std::thread;
impl<T> OffThreadExt for T
where T: Iterator + Send + 'static,
T::Item: Send + 'static
{
fn off_thread(self) -> mpsc::IntoIter<Self::Item> {
// Create a channel to transfer items from the worker thread.
let (sender, receiver) = mpsc::sync_channel(1024);
// Move this iterator to a new worker thread and run it there.
thread::spawn(move || {
for item in self {
if sender.send(item).is_err() {
break;
}
}
});
// Return an iterator that pulls values from the channel.
receiver.into_iter()
}
}rust[E0405] Error: cannot find trait `OffThreadExt` in this scope
╭─[command_12:1:1]
│
2 │ impl<T> OffThreadExt for T
│ ──────┬─────
│ ╰─────── not found in this scope
───╯
[E0433] Error: failed to resolve: use of undeclared crate or module `mpsc`
╭─[command_12:1:1]
│
6 │ fn off_thread(self) -> mpsc::IntoIter<Self::Item> {
│ ──┬─
│ ╰─── use of undeclared crate or module `mpsc`
│
│ Note: help: consider importing this module: `use std::sync::mpsc;
`
───╯
[E0433] Error: failed to resolve: use of undeclared crate or module `mpsc`
╭─[command_12:1:1]
│
8 │ let (sender, receiver) = mpsc::sync_channel(1024);
│ ──┬─
│ ╰─── use of undeclared crate or module `mpsc`
│
│ Note: help: consider importing this module: `use std::sync::mpsc;
`
───╯plaintextMulticonsumer Channels Using Mutexes#
pub mod shared_channel {
use std::sync::{Arc,Mutex};
use std::sync::mpsc::{channel,Sender,Receiver};
/// A thread-safe wrapper around a `Receiver`.
#[derive(Clone)]
pub struct SharedReceiver<T>(Arc<Mutex<Receiver<T>>>);
impl<T> Iterator for SharedReceiver<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let guard = self.0.lock().unwrap();
guard.recv().ok()
}
}
pub fn shared_channel<T>() -> (Sender<T>,SharedReceiver<T>) {
let (sender,receiver) = channel();
(sender,SharedReceiver(Arc::new(Mutex::new(receiver))))
}
}rust
Read/Write Locks (RwLock)#

Condition Variables (Condvar)#

Atomics#
use std::sync::atomic::{AtomicIsize,Ordering};
let atom = AtomicIsize::new(0);
atom.fetch_add(1, Ordering::SeqCst);rustThese methods may compile to specialized machine language instructions. On the x86-64 architecture, this .fetch_add() call compiles to a lock incq instruction, where an ordinary n += 1 might compile to a plain incq instruction or any number of variations on that theme. The Rust compiler also has to forgo some optimizations around the atomic operation, since—unlike a normal load or store—it can legiti‐ mately affect or be affected by other threads right away 这些方法可以编译成专门的机器语言指令。在x86-64架构上,this.fetch_add()调用编译成锁incq指令,其中普通的n+=1可能编译成普通的incq指令或该主题的任何数量的变体。Rust编译器还必须放弃围绕原子操作的一些优化,因为与正常的加载或存储不同,它可以合法地立即影响或受到其他线程的影响
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
let cancel_flag = Arc::new(AtomicBool::new(false));
let worker_cancel_flag = cancel_flag.clone();rustrustTraits and Generics#
[A] computer scientist tends to be able to deal with nonuniform structures—case 1, case 2, case 3—while a mathematician will tend to want one unifying axiom that governs an entire system. —Donald Knuth
use std::io::Write;
fn say_hello(out: &mut dyn Write) -> std::io::Result<()> {
out.write_all(b"hello world\n")?;
out.flush()
}rustuse std::fs::File;
let mut local_file = File::create("hello.txt")?;
say_hello(&mut local_file)?;rustlet mut bytes = vec![];
say_hello(&mut bytes)?;
assert_eq!(bytes,b"hello world\n");rustfn min<T: Ord>(v1: T,v2: T) -> T {
if v1 <= v2 {
v1
} else {
v2
}
}rust
Trait Objects#
use std::io::Write;
let mut buf: Vec<u8> = vec![];
let writer: dyn Write = buf;rust[E0308] Error: mismatched types
╭─[command_6:1:1]
│
4 │ let writer: dyn Write = buf;
│ ────┬──── ─┬─
│ ╰──────────── expected due to this
│ │
│ ╰─── expected `dyn Write`, found `Vec<u8>`
───╯
[E0277] Error: the size for values of type `dyn std::io::Write` cannot be known at compilation time
╭─[command_6:1:1]
│
4 │ let writer: dyn Write = buf;
│ ───┬── │
│ ╰────── doesn't have a size known at compile-time
│ │
│ ╰─ help: consider borrowing here: `&`
───╯plaintext{
let mut buf: Vec<u8> = vec![];
let writer: &mut dyn Write = &mut buf;
}rust()plaintext内存布局#

Generic Functions and Type Parameters#
let v1 = (0..100).collect();rust[E0282] Error: type annotations needed
╭─[command_11:1:1]
│
1 │ let v1 = (0..100).collect();
│ ─┬│
│ ╰── error: type annotations needed
│ │
│ ╰─ help: consider giving `v1` an explicit type: `: Vec<_>`
───╯plaintextlet v2 = (0..100).collect::<Vec<i32>>();rust
Defining and Implementing Traits#

Traits and Other People’s Types#
trait IsEmoji {
fn is_emoji(&self) -> bool;
}
impl IsEmoji for char {
fn is_emoji(&self) -> bool {
false
}
}
assert_eq!('$'.is_emoji(), false);rustSubtraits#

fn dot(v1: &[i64], v2: &[i64]) -> i64 {
let mut total = 0;
for i in 0 .. v1.len() {
total = total + v1[i] * v2[i];
}
total
}rustfn dot<N>(v1: &[N], v2: &[N]) -> N {
let mut total: N = 0;
for i in 0 .. v1.len() {
total = total + v1[i] * v2[i];
}
total
}rust[E0308] Error: mismatched types
╭─[command_19:1:1]
│
1 │ fn dot<N>(v1: &[N], v2: &[N]) -> N {
│ ┬
│ ╰── this type parameter
2 │ let mut total: N = 0;
│ ┬ ┬
│ ╰────── expected due to this
│ │
│ ╰── expected type parameter `N`, found integer
───╯
[E0369] Error: cannot multiply `N` by `N`
╭─[command_19:1:1]
│
1 │ fn dot<N>(v1: &[N], v2: &[N]) -> N {
│ │
│ ╰─ help: consider restricting type parameter `N`: `: std::ops::Mul`
│
4 │ total = total + v1[i] * v2[i];
│ ──┬── ┬ ──┬──
│ ╰──────────── N
│ │ │
│ ╰──────── error: cannot multiply `N` by `N`
│ │
│ ╰──── N
───╯plaintextuse std::ops::{Add, Mul};
fn dot<N: Add + Mul + Default>(v1: &[N], v2: &[N]) -> N {
let mut total = N::default();
for i in 0 .. v1.len() {
total = total + v1[i] * v2[i];
}
total
}rust[E0308] Error: mismatched types
╭─[command_20:1:1]
│
2 │ fn dot<N: Add + Mul + Default>(v1: &[N], v2: &[N]) -> N {
│ ┬ │
│ ╰───────────── this type parameter
│ │
│ ╰─ help: consider further restricting this bound: `<Output = N>`
│
5 │ total = total + v1[i] * v2[i];
│ ──┬── ──────┬──────
│ ╰──────────────────── expected because this is `N`
│ │
│ ╰──────── expected type parameter `N`, found associated type
───╯
[E0308] Error: mismatched types
╭─[command_20:1:1]
│
2 │ fn dot<N: Add + Mul + Default>(v1: &[N], v2: &[N]) -> N {
│ ┬ │
│ ╰─────── this type parameter
│ │
│ ╰─ help: consider further restricting this bound: `<Output = N>`
3 │ let mut total = N::default();
│ ──────┬─────
│ ╰─────── expected due to this value
│
5 │ total = total + v1[i] * v2[i];
│ ──────────┬──────────
│ ╰──────────── expected type parameter `N`, found associated type
───╯plaintextuse std::ops::{Add, Mul};
fn dot<N>(v1: &[N], v2: &[N]) -> N
where N: Add<Output=N> + Mul<Output=N> + Default + Copy
{
let mut total = N::default();
for i in 0 .. v1.len() {
total = total + v1[i] * v2[i];
}
total
}rustrustOperator Overloading#
Operator Overloading#

use std::ops::Add;
assert_eq!(4.125f32.add(5.75), 9.875);
assert_eq!(10.add(20), 10 + 20);rust
use std::ops::Add;
impl<T> Add for Complex<T>
where
T: Add<Output = T>,
{
type Output = Self;
fn add(self, rhs: Self) -> Self {
Complex {
re: self.re + rhs.re,
im: self.im + rhs.im,
}
}
}rust

let s = "d\x6fv\x65t\x61i\x6c".to_string();
let t = "\x64o\x76e\x74a\x69l".to_string();
assert!(s == t); // s and t are only borrowed...rust// ... so they still have their values here.
assert_eq!(format!("{} {}", s, t), "dovetail dovetail");rustassert!("ungula" != "ungulate");
assert!("ungula".ne("ungulate"));rustassert!(f64::is_nan(0.0 / 0.0));
assert_eq!(0.0 / 0.0 == 0.0 / 0.0, false);
assert_eq!(0.0 / 0.0 != 0.0 / 0.0, true);rustassert_eq!(0.0 / 0.0 < 0.0 / 0.0, false);
assert_eq!(0.0 / 0.0 > 0.0 / 0.0, false);
assert_eq!(0.0 / 0.0 <= 0.0 / 0.0, false);
assert_eq!(0.0 / 0.0 >= 0.0 / 0.0, false);rust
#[derive(Debug, PartialEq)]
struct Interval<T> {
lower: T, // inclusive
upper: T, // exclusive
}rustuse std::cmp::{Ordering, PartialOrd}
impl <T: PartialOrd> PartialOrd<Interval<T>> for Interval<T> {
fn partial_cmp(&self, other: &Interval<T>) -> Option<Ordering> {
if self == other {
Some(Ordering::Equal)
} else if self.lower >= other.upper {
Some(Ordering::Greater)
} else if self.upper <= other.lower {
Some(Ordering::Less)
} else {
None
}
}
}rustassert!(Interval { lower: 10, upper: 20 } < Interval { lower: 20, upper: 40 });
assert!(Interval { lower: 7, upper: 8 } >= Interval { lower: 0, upper: 1 });
assert!(Interval { lower: 7, upper: 8 } <= Interval { lower: 7, upper: 8 });
// Overlapping intervals aren't ordered with respect to each other.
let left = Interval { lower: 10, upper: 30 };
let right = Interval { lower: 20, upper: 40 };
assert!(!(left < right));
assert!(!(left >= right));rustIndex and IndexMut#
use std::collections::HashMap;
let mut m = HashMap::new();
m.insert("十", 10);
m.insert("百", 100);
m.insert("千", 1000);
m.insert("万", 1_0000);
m.insert("億", 1_0000_0000);
assert_eq!(m["十"], 10);
assert_eq!(m["千"], 1000);rustuse std::ops::Index;
assert_eq!(*m.index("十"), 10);
assert_eq!(*m.index("千"), 1000);rustlet mut desserts =
vec!["Howalon".to_string(), "Soan papdi".to_string()];
desserts[0].push_str(" (fictional)");
desserts[1].push_str(" (real)");
use std::ops::IndexMut;
(*desserts.index_mut(0)).push_str(" (fictional)");
(*desserts.index_mut(1)).push_str(" (real)");ruststruct Image<P> {
width: usize,
pixels: Vec<P>,
}rustimpl<P: Default + Copy> Image<P> {
fn new(width: usize, height:usize) -> Image<P> {
Image { width: width, pixels: vec![P::default();width * height], }
}
}rustimpl<P> std::ops::Index<usize> for Image<P> {
type Output = [P];
fn index(&self, index: usize) -> &Self::Output {
let start = index * self.width;
&self.pixels[start .. start + self.width]
}
}rustimpl<P> std::ops::IndexMut<usize> for Image<P> {
fn index_mut(&mut self, row: usize) -> &mut [P] {
let start = row * self.width;
&mut self.pixels[start..start + self.width]
}
}rustrustScience is nothing else than the search to discover unity in the wild variety of nature—or, more exactly, in the variety of our experience. Poetry, painting, the arts are the same search, in Coleridge’s phrase, for unity in variety. —Jacob Bronowski
Drop#
struct Appellation {
name: String,
nicknames: Vec<String>
}rustimpl Drop for Appellation {
fn drop(&mut self) {
println!("Droping {}",&self.name);
if !&self.nicknames.is_empty() {
println!("AKA {}",&self.nicknames.join(","));
}
println!("");
}
}rust{
let mut a = Appellation {
name: "Zeus".to_string(),
nicknames: vec!["cloud collector".to_string(),
"king of the gods".to_string()]
};
println!("before assignment");
a = Appellation { name: "Hera".to_string(), nicknames: vec![] };
println!("at end of block");
}rustbefore assignment
Droping Zeus
AKA cloud collector,king of the gods
at end of block
Droping Hera
()plaintextSized#

struct RcBox<T: ?Sized> {
ref_count: usize,
value: T,
}rustuse std::fmt::Display;
fn display(boxed: &RcBox<dyn Display>) {
println!("For your enjoyment: {}", &boxed.value);
}rust{
let boxed_lunch: RcBox<String> = RcBox {
ref_count: 1,
value: "lunch".to_string()
};
use std::fmt::Display;
let boxed_displayable: &RcBox<dyn Display> = &boxed_lunch;
display(&boxed_lunch);
}rustFor your enjoyment: lunch
()plaintextClone#

Copy#

Deref and DerefMut#
struct Selector<T> {
/// Elements available in this `Selector`.
elements: Vec<T>,
/// The index of the "current" element in `elements`. A `Selector`
/// behaves like a pointer to the current element.
current: usize
}rustuse std::ops::{Deref, DerefMut};
impl<T> Deref for Selector<T> {
type Target = T;
fn deref(&self) -> &T {
&self.elements[self.current]
}
}rustimpl<T> DerefMut for Selector<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.elements[self.current]
}
}rust[E0119] Error: conflicting implementations of trait `DerefMut` for type `Selector<_>`
╭─[command_17:1:1]
│
1 │ impl<T> DerefMut for Selector<T> {
│ ────────────────┬───────────────
│ ╰───────────────── conflicting implementation for `Selector<_>`
───╯plaintextlet mut s = Selector { elements: vec!['x', 'y', 'z'],
current: 2 };
// Because `Selector` implements `Deref`, we can use the `*` operator to
// refer to its current element.
assert_eq!(*s, 'z');rust// Assert that 'z' is alphabetic, using a method of `char` directly on a
// `Selector`, via deref coercion.
assert!(s.is_alphabetic());
// Change the 'z' to a 'w', by assigning to the `Selector`'s referent.
*s = 'w';
assert_eq!(s.elements, ['x', 'y', 'w']);rustlet s = Selector { elements: vec!["good", "bad", "ugly"],
current: 2 };
fn show_it(thing: &str) { println!("{}", thing); }
show_it(&s);rustuglyplaintextuse std::fmt::Display;
fn show_it_generic<T: Display>(thing: T) { println!("{}", thing); }
show_it_generic(&s);rust[E0277] Error: `Selector<&str>` doesn't implement `std::fmt::Display`
╭─[command_22:1:1]
│
2 │ fn show_it_generic<T: Display>(thing: T) { println!("{}", thing); }
│ ───┬───
│ ╰───── required by this bound in `show_it_generic`
3 │ show_it_generic(&s);
│ ───────┬─────── ┬
│ ╰──────────── required by a bound introduced by this call
│ │
│ ╰── `Selector<&str>` cannot be formatted with the default formatter
│ │
│ ╰── help: consider dereferencing here: `*`
───╯plaintextshow_it(&*s)rustugly
()plaintextshow_it(&s as &str)rustugly
()plaintextDefault#
use std::collections::HashSet;
let squares = [4, 9, 16, 25, 36, 49, 64];
let (powers_of_two, impure): (HashSet<i32>, HashSet<i32>)
= squares.iter().partition(|&n| n & (n-1) == 0);
assert_eq!(powers_of_two.len(), 3);
assert_eq!(impure.len(), 4);rustlet (upper, lower): (String, String)
= "Great Teacher Onizuka".chars().partition(|&c| c.is_uppercase());
assert_eq!(upper, "GTO");
assert_eq!(lower, "reat eacher nizuka");rustAsRef and AsMut#
/*
What open really wants is a &Path, the type representing a filesystem path. But with
this signature, open accepts anything it can borrow a &Path from—that is, anything
that implements AsRef<Path>. Such types include String and str, the operating sys‐
tem interface string types OsString and OsStr, and of course PathBuf and Path; see
the library documentation for the full list. This is what allows you to pass string liter‐
als to open:
*/
let dot_vim = std::fs::File::open("/home/realcpf/.vim");rustBorrow and BorrowMut#
From and Into#
use std::net::Ipv4Addr;
fn ping<A>(address: A) -> std::io::Result<bool>
where A: Into<Ipv4Addr>{
let ipv4_address = address.into();
std::io::Result::Ok(true)
}rustprintln!("{:?}", ping(Ipv4Addr::new(23, 21, 68, 141))); // pass an Ipv4Addr
println!("{:?}", ping([66, 146, 219, 98])); // pass a [u8; 4]
println!("{:?}", ping(0xd076eb94_u32)); // pass a u32rustOk(true)
Ok(true)
Ok(true)plaintextlet addr1 = Ipv4Addr::from([66, 146, 219, 98]);
let addr2 = Ipv4Addr::from(0xd076eb94_u32);rustlet text = "hello world".to_string();
let bytes: Vec<u8> = text.into();rustTryFrom and TryInto#
let huge = 2_000_000_000_000i64;
let smaller = huge as i32;
println!("{}", smaller); // -1454759936rust-1454759936plaintextuse std::convert::TryInto;
let smaller: i32 = huge.try_into().unwrap_or(i32::MAX);rustlet smaller: i32 = huge.try_into().unwrap_or_else(|_| {
if huge >= 0 {
i32::MAX
} else {
i32::MIN
}
});rustrustrust
>
> 
>
> 
