当我尝试编译此代码(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>()),
_ => {}
}
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
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
Run Code Online (Sandbox Code Playgroud)
我理解错误有助于告诉我在上面的行中用let f = &|c: &char| c.is_digit(10);(工作代码)声明闭包,但为什么这是必要的呢?
我也不确定为什么闭包必须包含两个引用 - &|c: &char|.不"abc123".chars()只是创建一个字符迭代器?
但为什么这有必要呢?
我真的不知道如何解释它比错误消息更好:
Run Code Online (Sandbox Code Playgroud)temporary value only lives until here temporary value created here
您正在语句中创建临时值(闭包本身),然后引用它.当语句结束时,该值被销毁 - 没有任何东西拥有它!问题是代码试图保持对现在被破坏的值的引用.如果编译器允许这样做,那么当它使用该引用时,谁知道将访问哪些随机数据.
闭包必须包含两个引用
那么,它不具备对.filter(|c| c.is_digit(10))工作得很好; 类型推断允许c自动输入为&char.在&c只有图案匹配,并自动取消引用值.这是多余的,因为方法调用会自动取消引用.
更大的问题是,代码尝试(克隆包含关闭,你不能做一个迭代器1,2,3,4问一个问题)之前(善良,人拒绝搜索).你选择解决这个问题的聪明方法是克隆对闭包的引用,这很好.
问题循环回到引用语句末尾被销毁的东西.
如果目标是忽略所有非数字,跳过前3位数字然后收集其余数字,您可以使用Iterator::skip:
let iter = "abc123".chars().filter(|c| c.is_digit(10));
let together: String = iter.skip(3).collect();
println!("{}", together);
Run Code Online (Sandbox Code Playgroud)
如果目标是仅取前三位数,当且仅当有三位数时,我可能总是收集这些数字,并检查是否结束:
let mut iter = "abc123".chars().filter(|c| c.is_digit(10));
let together: String = iter.by_ref().take(3).collect();
if iter.next().is_none() {
println!("{}", together);
}
Run Code Online (Sandbox Code Playgroud)
这用Iterator::by_ref.而不是使用迭代器,by_ref创建一个可变的引用.对迭代器的可变引用也实现了Iterator,所以调用take并collect正常工作.但是,当这些完成后,iter仍然有效.
| 归档时间: |
|
| 查看次数: |
949 次 |
| 最近记录: |