当我尝试编译此代码(playground)时:
fn main() {
let iter = "abc123".chars().filter(&|&c: &char| c.is_digit(10));
match iter.clone().take(3).count() {
3 => println!("{}", iter.collect::<String>()),
_ => {}
}
}
我收到以下错误:
error: borrowed value does not live long enough
--> test.rs:2:41
|
2 | let iter = "abc123".chars().filter(&|c: &char| c.is_digit(10));
| ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value only lives until here
| |
| temporary value created here
...
7 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
我理解错误有助于告诉我在 let f = &|c: &char| c.is_digit(10);
(working code)上面的行中声明闭包,但为什么这是必要的呢?
我也不确定为什么闭包必须包含两个引用 - &|c: &char|
. 不是 "abc123".chars()
只是创建一个字符迭代器?
1 回答
我真的不知道如何解释它比错误消息更好:
您正在语句中创建临时值(闭包本身),然后引用它 . 当语句结束时,该值被销毁 - 没有任何东西拥有它!问题是代码试图保持对现在被破坏的值的引用 . 如果编译器允许这样做,那么当它使用该引用时,谁知道将访问哪些随机数据 .
嗯,它不必 .
filter(|c| c.is_digit(10))
工作得很好;类型推断允许c
自动输入&char
. 仅&c
模式匹配并自动取消引用该值 . 这是多余的,因为方法调用automatically dereference .更大的问题是代码试图克隆包含闭包的迭代器,你不能这样做(1,2,3,4(善良,人们在提问之前拒绝搜索)) . 你选择解决这个问题的聪明方法是克隆对闭包的引用,这很好 .
问题循环回到引用语句末尾被销毁的东西 .
If 目标是忽略所有非数字,跳过前3位数然后收集其余数字,你可以使用Iterator::skip:
If 目标是仅取前三位数,当且仅当有三位数时,我可能总是收集这些数字,并检查是否结束:
这使用Iterator::by_ref .
by_ref
不是使用迭代器,而是创建一个可变引用 . 对迭代器的可变引用也实现Iterator
,因此调用take
和collect
工作正常 . 但是,当这些完成后,iter
仍然有效 .