我每晚运行Rust(rustc 1.50.0-nightly (f0f68778f 2020-12-09)
)。
我了解了一种接受(作为函数参数)可以转换为迭代器的任意对象的方法。我还学习了一种方法,该方法允许使用String
接受&str
和&str
(可能还可以接受其他类型的可以转换为AsRef<str>
的类型)。
到目前为止,我已经提供了以下测试代码来证明这一点:
use std::env;
fn main() {
let v1: Vec<String> = vec!["a".to_string(), "b".to_string()];
let v2: Vec<&str> = vec!["a", "b"];
let args: env::Args = env::args();
fun1(&v1);
fun1(&v2);
fun1(v1);
fun1(v2);
fun1(args);
}
fn fun1<I, T>(args: I)
where
I: IntoIterator<Item = T>,
T: AsRef<str>,
{
println!("=================");
for item in args {
println!("{}", item.as_ref());
}
}
它可以很好地编译并且运行良好。现在,我的愿望是将args
从IntoIterator<Item=AsRef<str>>
转换为Iterator<Item=&str>
,这样我就不必在整个函数中处理那些as_ref()
调用。在此示例中,这是一个简单的循环,它在一个地方调用as_ref()
,但是我在这里不共享的代码更加复杂-我想避免每次从该迭代器中获取下一个元素时都调用as_ref()
。不幸的是,我这样做的天真尝试是行不通的:
use std::env;
fn main() {
let v1: Vec<String> = vec!["a".to_string(), "b".to_string()];
let v2: Vec<&str> = vec!["a", "b"];
let args: env::Args = env::args();
fun2(&v1);
fun2(&v2);
fun2(v1);
fun2(v2);
fun2(args);
}
fn fun2<I, T>(args: I)
where
I: IntoIterator<Item = T>,
T: AsRef<str>,
{
println!("=================");
let iter = args.into_iter();
let mapped = iter.map(|item| item.as_ref());
for item in mapped {
println!("{}", item);
}
}
% rustc test1.rs
error[E0515]: cannot return value referencing function parameter `item`
--> test1.rs:23:34
|
23 | let mapped = iter.map(|item| item.as_ref());
| ----^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `item` is borrowed here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0515`.
在我的一生中,我无法解决这个问题(我使用各种方法玩耍,而我所得到的只是像这样的错误),我仔细研究了之前的一些问题,但没有运气。在Rust中甚至有办法实现这一目标吗?
最佳答案
如果不将迭代器中的所有数据收集到Vec
或类似文件中,这是不可能的。这是因为Iterator<Item = &str>
要求切片后面的字符串数据不归迭代器所有,但是Iterator<Item = String>
确实通过使用拥有的类型来拥有字符串数据。
这也解释了为什么将向量收集为有效的原因。在那种情况下,字符串数据将由向量而不是迭代器拥有,这满足了Iterator<Item = &str>
不拥有字符串数据的要求。
fn fun2<I, T>(args: I)
where
I: IntoIterator<Item = T>,
T: AsRef<str>,
{
println!("=================");
let vec: Vec<T> = args.into_iter().collect();
let mapped = vec.iter().map(|item| item.as_ref());
for item in mapped {
println!("{}", item);
}
}
请注意,并非总是T: AsRef<str>
类型拥有字符串数据。例如,如果T = &str
,则不是。不幸的是,通用代码必须处理通用参数所允许的所有情况,因此,如果代码不处理T = String
情况,它将无法编译。请注意,在
T = &str
的情况下,上述示例中的向量不拥有字符串数据。仍然可以,因为在这种情况下,字符串数据完全由fun2
之外的其他某个集合拥有,并且还满足Iterator<Item = &str>
一定不能拥有字符串数据的要求。
关于rust - 如何在Rust中将IntoIterator <Item = AsRef <str >>转换为Iterator <Item =&str>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65250496/