【发布时间】:2017-11-17 17:48:23
【问题描述】:
我有这个玩具示例,但这是我想要完成的:
fn lazy_vec() {
let vec: Vec<i64> = vec![1, 2, 3, 4, 5];
let mut iter: Box<Iterator<Item = i64>> = Box::new(vec.into_iter());
iter = Box::new(iter.map(|x| x + 1));
// potentially do additional similar transformations to iter
println!("{:?}", iter.collect::<Vec<_>>());
}
这(如果我没记错的话)是一个惰性迭代器模式,实际的map 操作在调用.collect() 之前不会发生。我想对切片做同样的事情:
fn lazy_slice() {
let vec: Vec<i64> = vec![1, 2, 3, 4, 5];
let slice: &[i64] = &vec[..3];
let mut iter: Box<Iterator<Item = i64>> = Box::new(slice.into_iter());
iter = Box::new(iter.map(|x| x + 1));
// potentially do additional similar transformations to iter
println!("{:?}", iter.collect::<Vec<_>>());
}
这会导致类型不匹配:
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, i64> as std::iter::Iterator>::Item == i64`
--> src/main.rs:4:47
|
4 | let mut iter: Box<Iterator<Item = i64>> = Box::new(slice.into_iter());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found i64
|
= note: expected type `&i64`
found type `i64`
= note: required for the cast to the object type `std::iter::Iterator<Item=i64>`
我不知道我需要做什么来解决这个错误。第二个note 让我觉得我需要:
iter = Box::new(iter.map(|x| x + 1) as Iterator<Item = i64>);
或
iter = Box::new(iter.map(|x| x + 1)) as Box<Iterator<Item = i64>>;
根据确切的语法(例如 expected reference, found i64 或 expected i64, found &i64),这些失败并出现其他错误。我尝试了其他方法来声明所涉及的类型,但我基本上只是在一些地方盲目地添加&和*,并没有取得任何进展。
我在这里缺少什么?为了编译,我需要改变什么?
编辑
这里有一个更具体的例子——我需要iter 成为mut,这样我就可以在实际调用.collect() 之前组合未知数量的此类转换。我的印象是这是一种比较常见的模式,如果不正确,请道歉。
fn lazy_vec(n: i64) {
let vec: Vec<i64> = vec![1, 2, 3, 4, 5];
let mut iter: Box<Iterator<Item = i64>> = Box::new(vec.into_iter());
for _ in 0..n {
iter = Box::new(iter.map(|x| x + 1));
}
println!("{:?}", iter.collect::<Vec<_>>());
}
我知道我可以以更简单的方式重写此特定任务(例如,将 n 添加到每个元素的单个 map) - 这是我遇到的问题的过度简化的 MCVE。我的问题是这适用于lazy_vec,但我不知道如何对切片做同样的事情。
编辑 2
我刚刚学习 Rust,其中一些术语和概念对我来说是新的。这是我在 Python 中的设想,用于比较。我的意图是对切片做同样的事情,我目前可以对向量做同样的事情。
#!/usr/bin/env python3
import itertools
ls = [i for i in range(10)]
def lazy_work(input):
for i in range(10):
input = (i + 1 for i in input)
# at this point no actual work has been done
return input
print("From list: %s" % list(lazy_work(ls)))
print("From slice: %s" % list(lazy_work(itertools.islice(ls, 5))))
显然在 Python 中打字没有问题,但希望这能更清楚地表明我的意图?
【问题讨论】:
-
@Shepmaster 添加了更多细节,希望这能让它更清楚吗?我的导师分享了向量的
Box<Iterator<_>>模式,所以这就是我开始的。如果有其他懒惰组合的方法,我很想听听。 -
问题是类型不匹配。
.map的结果是值的迭代器,但您有引用,因此您 必须 在某处分配一个新变量,因为您需要一个具有正确类型的变量。你考虑过play.rust-lang.org/… 之类的东西吗? -
@loganfsmyth 是的,我意识到这是一个类型问题 - 因此问题:) 你的建议看起来很有希望!我试试看,你想把它作为答案发布吗?
-
不,其他答案几乎已经涵盖了它。
标签: rust