fnprint_number(n: Number) { ifletNumber { odd: true, value } = n { println!("Odd number: {}", value); } elseifletNumber { odd: false, value } = n { println!("Even number: {}", value); } }
// this prints: // Odd number: 1 // Even number: 2
match匹配也是模式,就像if let:
1 2 3 4 5 6 7 8
fnprint_number(n: Number) { match n { Number { odd: true, value } => println!("Odd number: {}", value), Number { odd: false, value } => println!("Even number: {}", value), } }
// this prints the same as before
注意match匹配必须是详尽的,至少需要一个分支与之匹配:
1 2 3 4 5 6 7 8
fnprint_number(n: Number) { match n { Number { value: 1, .. } => println!("One"), Number { value: 2, .. } => println!("Two"), Number { value, .. } => println!("{}", value), // if that last arm didn't exist, we would get a compile-time error } }
// the `Neg` trait is used to overload `-`, the // unary minus operator. implstd::ops::Neg forNumber { typeOutput = Number;
fnneg(self) -> Number { Number { value: -self.value, odd: self.odd, } } }
fnmain() { letn = Number { odd: true, value: 987 }; letm = -n; // this is only possible because we implemented `Neg` println!("{}", m.value); // prints "-987" }
fnmain() { leta: i32 = 15; letb = a; // `a` is copied letc = a; // `a` is copied again }
下面的代码也正常:
1 2 3 4 5 6 7 8 9
fnprint_i32(x: i32) { println!("x = {}", x); }
fnmain() { leta: i32 = 15; print_i32(a); // `a` is copied print_i32(a); // `a` is copied again }
但是Number类型没有实现Copy,所以下面的代码不工作:
1 2 3 4 5
fnmain() { letn = Number { odd: true, value: 51 }; letm = n; // `n` is moved into `m` leto = n; // error: use of moved value: `n` }
下面的代码也不行:
1 2 3 4 5 6 7 8 9
fnprint_number(n: Number) { println!("{} number {}", if n.odd { "odd" } else { "even" }, n.value); }
fnmain() { letn = Number { odd: true, value: 51 }; print_number(n); // `n` is moved print_number(n); // error: use of moved value: `n` }
但是如果print_number使用一个不可变的引用就可以:
1 2 3 4 5 6 7 8 9
fnprint_number(n: &Number) { println!("{} number {}", if n.odd { "odd" } else { "even" }, n.value); }
fnmain() { letn = Number { odd: true, value: 51 }; print_number(&n); // `n` is borrowed for the time of the call print_number(&n); // `n` is borrowed again }
如果变量被声明为可变的,则函数参数使用可变引用也可以工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
fninvert(n: &mut Number) { n.value = -n.value; }
fnprint_number(n: &Number) { println!("{} number {}", if n.odd { "odd" } else { "even" }, n.value); }
fnmain() { // this time, `n` is mutable letmut n = Number { odd: true, value: 51 }; print_number(&n); invert(&mut n); // `n is borrowed mutably - everything is explicit print_number(&n); }
impl<T> Option<T> { fnunwrap(self) -> T { // enums variants can be used in patterns: matchself { Self::Some(t) => t, Self::None => panic!(".unwrap() called on a None option"), } } }
use self::Option::{None, Some};
fnmain() { leto1: Option<i32> = Some(128); o1.unwrap(); // this is fine
leto2: Option<i32> = None; o2.unwrap(); // this panics! }
// output: thread 'main' panicked at '.unwrap() called on a None option', src/main.rs:11:27
fnmain() { letmut x = 42; letx_ref = &x; x = 13; println!("x_ref = {}", x_ref); // error: cannot assign to `x` because it is borrowed }
当不可变地借用时,不能同时可变地的借用:
1 2 3 4 5 6 7
fnmain() { letmut x = 42; letx_ref1 = &x; letx_ref2 = &mut x; // error: cannot borrow `x` as mutable because it is also borrowed as immutable println!("x_ref1 = {}", x_ref1); }
函数参数中的引用也有生命周期:
1 2 3 4
fnprint(x: &i32) { // `x` is borrowed (from the outside) for the // entire time this function is called. }
fnmain() { letname = format!("fasterthan{}", "lime"); letp = Person { name: name }; // `name` was moved into `p`, their lifetimes are no longer tied. }
fnmain() { letext = { letname = String::from("Read me. Or don't.txt"); file_ext(&name).unwrap_or("") // error: `name` does not live long enough }; println!("extension: {:?}", ext); }
fnfor_each_planet<F>(f: F) where F: Fn(&'staticstr) { f("Earth"); f("Mars"); f("Jupiter"); } fnmain() { letgreeting = String::from("Good to see you"); for_each_planet(|planet| println!("{}, {}", greeting, planet)); // our closure borrows `greeting`, so it cannot outlive it }
比如下面的代码就不工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
fnfor_each_planet<F>(f: F) where F: Fn(&'staticstr) + 'static// `F` must now have "'static" lifetime { f("Earth"); f("Mars"); f("Jupiter"); }
fnmain() { letgreeting = String::from("Good to see you"); for_each_planet(|planet| println!("{}, {}", greeting, planet)); // error: closure may outlive the current function, but it borrows // `greeting`, which is owned by the current function }
但是下面的代码就可以:
1 2 3 4 5 6
fnmain() { letgreeting = String::from("You're doing great"); for_each_planet(move |planet| println!("{}, {}", greeting, planet)); // `greeting` is no longer borrowed, it is *moved* into // the closure. }
FnMut需要可变地借用去调用,所以它同时只能调用一次。
下面的代码合法:
1 2 3 4 5 6 7 8 9 10 11
fnfoobar<F>(f: F) where F: Fn(i32) ->i32 { println!("{}", f(f(2))); } fnmain() { foobar(|x| x * 2); }
// output: 8
下面的代码不合法:
1 2 3 4 5 6 7 8 9 10
fnfoobar<F>(mut f: F) where F: FnMut(i32) ->i32 { println!("{}", f(f(2))); // error: cannot borrow `f` as mutable more than once at a time } fnmain() { foobar(|x| x * 2); }
fnfoobar<F>(f: F) where F: Fn(i32) ->i32 { println!("{}", f(f(2))); } fnmain() { letmut acc = 2; foobar(|x| { acc += 1; // error: cannot assign to `acc`, as it is a // captured variable in a `Fn` closure. // the compiler suggests "changing foobar // to accept closures that implement `FnMut`" x * acc }); }
FnOnce闭包只会被调用一次。因为一些闭包会把move进来的变量在返回值中move out:
1 2 3 4 5 6 7 8 9 10 11 12 13
fnfoobar<F>(f: F) where F: FnOnce() ->String { println!("{}", f()); } fnmain() { lets = String::from("alright"); foobar(move || s); // `s` was moved into our closure, and our // closures moves it to the caller by returning // it. Remember that `String` is not `Copy`. }
这是自然限制的,因为FnOnce闭包在调用的时候需要被move:
1 2 3 4 5 6 7
fnfoobar<F>(f: F) where F: FnOnce() ->String { println!("{}", f()); println!("{}", f()); // error: use of moved value: `f` }
而且你确保使用move调用闭包,它依然是非法的:
1 2 3 4 5 6
fnmain() { lets = String::from("alright"); foobar(move || s); foobar(move || s); // use of moved value: `s` }
fnmain() { foriinvec![52, 49, 21] { println!("I like the number {}", i); } }
或者处理slice:
1 2 3 4 5 6 7 8 9 10
fnmain() { foriin &[52, 49, 21] { println!("I like the number {}", i); } }
// output: // I like the number 52 // I like the number 49 // I like the number 21
或者是一个实际的迭代器:
1 2 3 4 5 6 7 8 9 10 11 12 13
fnmain() { // note: `&str` also has a `.bytes()` iterator. // Rust's `char` type is a "Unicode scalar value" forcin"rust".chars() { println!("Give me a {}", c); } }
// output: // Give me a r // Give me a u // Give me a s // Give me a t
fnmain() { // you can use `.into()` to perform conversions // between various types, here `&'static str` and `String` lettest = make_tester("hunter2".into()); println!("{}", test("******")); println!("{}", test("hunter2")); }