一切正常。 先打印 person 的全部内容,然后是模式匹配。 但是尝试在函数末尾添加上这行,你会得到一个编译错误:
error[E0382]: use of partially moved value: `person`
--> main.rs:18:41
|
9 | Some(name) => println!("Name is {}", name),
| ---- value moved here
...
18 | println!("Full Person value: {:?}", person);
| ^^^^^^ value used here after move
|
= note: move occurs because the value has type `std::string::String`, which does not implement the `Copy` trait
error: aborting due to previous error
注意:这是我使用的Rust编译器1.30.1的错误。 但是,已经有计划来改善这种情况。
问题在于我们已经消耗了 person 的一部分,因此无法打印它。 我们可以通过再次设置来解决此问题。 让 person 参数可变,然后使用默认的None 值填充移动的 person.name:
fn print_person(mut person: Person) {
match person.name {
Some(name) => println!("Name is {}", name),
None => println!("No name provided"),
}
match person.age {
Some(age) => println!("Age is {}", age),
None => println!("No age provided"),
}
person.name = None;
println!("Full Person value: {:?}", person);
}
编译运行,但现在输出结果令人困惑:
Name is Alice
Age is 30
Full Person value: Person { name: None, age: Some(30) }
注意最后一行中name的值是None,理想情况下应该是 Some (Alice)。 我们可以做得更好,通过返回 match 中的 name:
person.name = match person.name {
Some(name) => {
println!("Name is {}", name);
Some(name)
},
None => {
println!("No name provided");
None
}
};
fn print_person(person: Person) {
match person.name {
Some(ref name) => println!("Name is {}", name),
None => println!("No name provided"),
}
match &mut person.age {
Some(age) => {
println!("Age is {}", age);
age += 1;
}
None => println!("No age provided"),
}
println!("Full Person value: {:?}", person);
}
编译器抱怨:age是一个 &mut u32,但是我们试图在其上使用 += :
error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut u32`
--> src/main.rs:16:13
|
16 | age += 1;
| ---^^^^^
| |
| cannot use `+=` on type `&mut u32`
|
= help: `+=` can be used on 'u32', you can dereference `age`: `*age`
根据编译器的踏实,我们需要采用取消年龄引用。 但又出现一个错误:
error[E0596]: cannot borrow field `person.age` of immutable binding as mutable
--> src/main.rs:13:16
|
7 | fn print_person(person: Person) {
| ------ consider changing this to `mut person`
...
13 | match &mut person.age {
| ^^^^^^^^^^ cannot mutably borrow field of immutable binding
error: aborting due to previous error
同样,编译器准确地告诉我们如何解决这个问题: 使 person 可变。 继续,做出改变,一切都会顺利进行。
error[E0599]: no method named `collect` found for type `Single<{integer}>` in the current scope
--> src/main.rs:12:39
|
1 | struct Single<T> {
| ---------------- method `collect` not found for this
...
12 | let actual: Vec<u32> = single(42).collect();
| ^^^^^^^
|
= note: the method `collect` exists but the following trait bounds were not satisfied:
`&mut Single<{integer}> : std::iter::Iterator`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `collect`, perhaps you need to implement it:
candidate #1: `std::iter::Iterator`
impl<T> Iterator for Single<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
self.next
}
}
不幸的是,这并不奏效:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:21:9
|
21 | self.next
| ^^^^ cannot move out of borrowed content
error: aborting due to previous error
哦,对。 我们不能将结果值移出,因为我们的 next 函数只能可变借用 self。 让我们尝试一些模式匹配:
match self.next {
Some(next) => Some(next),
None => None,
}
fn next(&mut self) -> Option<T> {
let res = self.next;
self.next = None;
res
}
不,编译器仍然不满意! 我想我们只需要放弃对单一迭代器的宏伟愿景。 我们当然可以作弊:
fn next(&mut self) -> Option<T> {
None
}
但是,尽管编译完成,但它在运行时未能通过我们的测试:
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `[42]`,
right: `[]`', src/main.rs:13:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.
万岁! 但是让我们把函数变得更复杂一点。 现在我们需要一个函数,它将接受两个 Person,并返回 age 较大的 Person 的 name。 这听起来相当容易写:
struct Person {
name: String,
age: u32,
}
fn get_older_name(person1: &Person, person2: &Person) -> &String {
if person1.age >= person2.age {
&person1.name
} else {
&person2.name
}
}
fn main() {
let alice = Person {
name: String::from("Alice"),
age: 30,
};
let bob = Person {
name: String::from("Bob"),
age: 35,
};
let name = get_older_name(&alice, &bob);
println!("Older person: {}", name);
}
不幸的是,编译器非常生我们的气:
error[E0106]: missing lifetime specifier
--> src/main.rs:6:58
|
6 | fn get_older_name(person1: &Person, person2: &Person) -> &String {
| ^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `person1` or `person2`
我们仍然从编译器得到一个错误,因为我们的返回值没有生命周期。 我们应该选择 a 还是 b? 或者我们可以创建一个新的 c 并尝试一下? 让我们从 “ a” 开始。 我们得到了错误消息:
error[E0623]: lifetime mismatch
--> src/main.rs:10:9
|
6 | fn get_older_name<'a, 'b>(person1: &'a Person, person2: &'b Person) -> &'a String {
| ---------- ----------
| |
| this parameter and the return type are declared with different lifetimes...
...
10 | &person2.name
| ^^^^^^^^^^^^^ ...but data from `person2` is returned here
这是有道理的: 因为我们的结果可能来自于 person2,我们不能保证 ‘ a 寿命参数小于或等于 ’ b 寿命参数。 幸运的是,我们可以明确地声明,就像我们声明类型实现了一些 traits 一样:
fn main() {
let alice = Person {
name: String::from("Alice"),
age: 30,
};
foo(&alice);
}
fn foo(alice: &Person) {
let bob = Person {
name: String::from("Bob"),
age: 35,
};
let name = get_older_name(&alice, &bob);
println!("Older person: {}", name);
}
Alice 的生命周期显然比Bob的生命周期要长。 但是,函数签名中生存期的语义是所有值至少具有相同的生存期。 如果他们碰巧活得久一点,没有伤害,没有犯规。
多生命周期参数需求
那么,我们能否举出一个绝对需要多个生存期参数的例子呢? 当然!
fn message_and_return(msg: &String, ret: &String) -> &String {
println!("Printing the message: {}", msg);
ret
}
fn main() {
let name = String::from("Alice");
let msg = String::from("This is the message");
let ret = message_and_return(&msg, &name);
println!("Return value: {}", ret);
}
fn main() {
let name = String::from("Alice");
let ret = foo(&name);
println!("Return value: {}", ret);
}
fn foo(name: &String) -> &String {
let msg = String::from("This is the message");
message_and_return(&msg, &name)
}
现在编译器不高兴了:
error[E0597]: `msg` does not live long enough
--> src/main.rs:14:25
|
14 | message_and_return(&msg, &name)
| ^^^ borrowed value does not live long enough
15 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 12:1...
--> src/main.rs:12:1
|
12 | / fn foo(name: &String) -> &String {
13 | | let msg = String::from("This is the message");
14 | | message_and_return(&msg, &name)
15 | | }
| |_^
fn print_vals(vref: &[u32]) {
let v = *vref;
for i in v {
println!("{}", i);
}
}
编译器又跟我们发脾气了:
error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
--> src/main.rs:7:9
|
7 | let v = *vref;
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u32]`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-sized>
= note: all local variables must have a statically known size
error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
--> src/main.rs:8:14
|
8 | for i in v {
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u32]`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-sized>
= note: required by `std::iter::IntoIterator::into_iter`
error[E0277]: the trait bound `[u32]: std::iter::Iterator` is not satisfied
--> src/main.rs:8:14
|
8 | for i in v {
| ^ `[u32]` is not an iterator; maybe try calling `.iter()` or a similar method
|
= help: the trait `std::iter::Iterator` is not implemented for `[u32]`
= note: required by `std::iter::IntoIterator::into_iter`
fn main() {
let bytearray1: &[u8; 22] = b"Hello World in binary!";
let bytearray2: &[u8] = b"Hello World in binary!";
println!("{:?}", bytearray1);
println!("{:?}", bytearray2);
}