我正在将Rust的迭代工具1中的笛卡儿产品代码重构为学习Rust的一种方法。笛卡尔积是由Iterator I和IntoIterator J形成的,IntoIterator J被多次转换成迭代器并进行迭代。
到目前为止,我有下面的代码,这是迭代工具源代码中的代码的一个小修改。最大的改变是指定特定类型(i8),而不是使用泛型类型。
struct Product {
a: dyn Iterator<Item=i8>,
a_cur: Option<i8>,
b: dyn IntoIterator<Item=i8, IntoIter=dyn Iterator<Item=i8>>,
b_iter: dyn Iterator<Item=i8>
}
impl Iterator for Product {
type Item = (i8, i8);
fn next(&mut self) -> Option<Self::Item> {
let elt_b = match self.b_iter.next() {
None => {
self.b_iter = self.b.into_iter();
match self.b_iter.next() {
None => return None,
Some(x) => {
self.a_cur = self.a.next();
x
}
}
}
Some(x) => x
};
match self.a_cur {
None => None,
Some(ref a) => {
Some((a, elt_b))
}
}
}
}
fn cp(i: impl Iterator<Item=i8>, j: impl IntoIterator<Item=i8>) -> Product {
let p = Product{
a: i,
a_cur: i.next(),
b: j,
b_iter: j.into_iter()};
return p
}
fn main() {
for foo in cp(vec![1,4,7], vec![2,3,9]) {
println!("{:?}", foo);
}
}不幸的是,编译器给出了我无法修复的错误。我尝试了编译器所建议的修复,但是当我做它们时,我得到了更多“在编译时不知道大小”的错误。
我特别困惑,因为Rust的迭代工具库(下面的链接)中的实现具有非常相似的结构,不需要指定生命周期、借用、使用框或dyn关键字。我很想知道我改变了什么,这导致了Rust编译器建议使用借用和/或盒子。
error[E0277]: the size for values of type `(dyn Iterator<Item = i8> + 'static)` cannot be known at compilation time
--> src/main.rs:15:8
|
15 | a: dyn Iterator<Item=i8>,
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Iterator<Item = i8> + 'static)`
= note: only the last field of a struct may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
15 | a: &dyn Iterator<Item=i8>,
| ^
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
15 | a: Box<dyn Iterator<Item=i8>>,
| ^^^^ ^
error[E0277]: the size for values of type `(dyn IntoIterator<Item = i8, IntoIter = (dyn Iterator<Item = i8> + 'static)> + 'static)` cannot be known at compilation time
--> src/main.rs:17:8
|
17 | b: dyn IntoIterator<Item=i8, IntoIter=dyn Iterator<Item=i8>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn IntoIterator<Item = i8, IntoIter = (dyn Iterator<Item = i8> + 'static)> + 'static)`
= note: only the last field of a struct may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
17 | b: &dyn IntoIterator<Item=i8, IntoIter=dyn Iterator<Item=i8>>,
| ^
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
17 | b: Box<dyn IntoIterator<Item=i8, IntoIter=dyn Iterator<Item=i8>>>,
| ^^^^ ^
error: aborting due to 2 previous errors1文档在https://nozaq.github.io/shogi-rs/itertools/trait.Itertools.html#method.cartesian_product,代码在https://github.com/rust-itertools/itertools/blob/master/src/adaptors/mod.rs#L286。
发布于 2021-07-20 11:59:32
您不仅更改了项目类型,还删除了泛型迭代器。在itertools箱中,有:
pub struct Product<I, J>
where I: Iterator
{
a: I,
…这意味着a是一个迭代器,它的确切类型将由用户指定(但仍在编译时)。
您已经删除了泛型I参数,而是编写了:
pub struct Product
{
a: dyn Iterator<Item=i8>,
…如果成功的话,这将意味着a是一个迭代器,其项类型为u8,但其确切类型将在运行时指定。因此,在编译时,编译器无法知道a的确切类型,也不知道它应该分配多少空间来存储a在Product中。
如果您希望您的笛卡尔产品适用于项目为u8的任何迭代器,则需要保留带有额外约束的泛型参数I:
pub struct Product<I, J>
where I: Iterator<Item=u8>
{
a: I,
…对于J in impl Iterator,也需要进行类似的更改。
https://stackoverflow.com/questions/68454246
复制相似问题