Recursion 如何在没有运行时多态性的情况下在迭代器上执行N次“平面映射”(或类似操作)?

Recursion 如何在没有运行时多态性的情况下在迭代器上执行N次“平面映射”(或类似操作)?,recursion,rust,iterator,traits,recursive-type,Recursion,Rust,Iterator,Traits,Recursive Type,我希望能够重复一个过程,在这个过程中,我们正在迭代的集合被改变n次。n仅在运行时已知,并且可以由用户指定,因此我们无法将其硬编码到类型中 一种通过在迭代之间收集数据来使用中间数据结构的方法是可行的,如下所示: let n = 10; let mut vec1 = vec![1, 2, 3]; { for _index in 0..n { let temp_vec = vec1.into_iter().flat_map(|x| vec![x, x * 2]).collec

我希望能够重复一个过程,在这个过程中,我们正在迭代的集合被改变n次。n仅在运行时已知,并且可以由用户指定,因此我们无法将其硬编码到类型中

一种通过在迭代之间收集数据来使用中间数据结构的方法是可行的,如下所示:

let n = 10;

let mut vec1 = vec![1, 2, 3];
{
    for _index in 0..n {
        let temp_vec = vec1.into_iter().flat_map(|x| vec![x, x * 2]).collect();
        vec1 = temp_vec;
    }
}
然而,这似乎是浪费,因为我们正在创建中间数据结构,所以我继续寻找直接链接迭代器的解决方案

起初,我认为人们可以做一些事情,比如:

let mut iter = vec![1, 2, 3].into_iter();
for index in 0..n {
    iter = iter.flat_map(|x| vec![x, x * 2].into_iter());
}
但是,这不起作用,因为在Rust中,迭代器上的所有函数都返回自己的“复合迭代器”结构。例如,在Haskell中,迭代器上的函数返回适当类型的结果迭代器,这不会成为“越来越大的复合类型”。 将其重写为递归函数也有类似的问题,因为a I返回“某种类型的迭代器”,其类型接近-由于递归,无法手动写出,而b这种类型在基本情况下与递归情况不同

我发现有条件地返回一个或另一个迭代器类型,以及使用impl iterator指示返回实现迭代器特性的具体类型,但我们不关心它的确切性质。 下面的代码中实现了一个与链接答案中的代码类似的示例,可能是_flatmap。这很有效

但是,我不想在传入的迭代器上运行平面映射零次或一次,而是N次。因此,我对代码进行了调整,使其能够递归地调用自己,深度达到N

尝试执行此操作时,会使Rust编译器发出错误[E0720]:不透明类型扩展为递归类型:

错误[E0720]:不透明类型扩展为递归类型 ->src/main.rs:16:65 | 16 | fn rec|u flatmapier:T,深度:usize->impl迭代器{ |^^^^^^^^^^^^^^^^^^^^^^^^^^扩展为递归类型 | =注意:扩展类型为`other::other` 我被卡住了

因为不管你多久使用一次平面映射,最终的答案是一个整数向量上的迭代器,似乎应该有一种只使用一个具体返回类型来编写这个函数的方法

这是可能的吗?有没有一种不用运行时多态性就可以摆脱这种情况的方法

我相信/希望没有动态多态特性对象或类似对象的解决方案是可能的,因为无论您调用flat_map的频率有多高,最终结果至少在道义上应该具有相同的类型。我希望有一种方法可以将不匹配的嵌套FlatMap结构以某种方式固定在匹配的单个静态类型中

有没有一种方法可以在没有运行时多态性的情况下解决这个问题

没有

要使用特征对象解决此问题,请执行以下操作:

let mut iter: Box<dyn Iterator<Item = i32>> = Box::new(vec![1, 2, 3].into_iter());
for _ in 0..n {
    iter = Box::new(iter.flat_map(|x| vec![x, x * 2].into_iter()));
}
不管你称之为平面图的频率有多高,最终结果至少在道德上应该是相同的类型

我不知道哪种道德适用于类型系统,但FlatMap和FlatMap内存中的文字大小很可能不同,它们是不同的类型

另见:


@Shepmaster我已经澄清了这个问题:我相信/希望没有动态多态性特征对象或类似对象的解决方案是可能的,因为无论您调用flat_map的频率有多高,最终结果至少在道义上应该具有相同的类型。因此我希望有一种方法将不匹配的嵌套FlatMap结构固定在匹配的sin中不知何故,gle静态类型。n只能在运行时知道,并且可以由用户指定。那么为什么您认为它可以被编码到类型系统中,而不是动态解析?我不知道Haskell会如何处理它,但我想象类似于Box的东西。如果n在编译时未知,编译器无法生成任何n。@trentcl你可能是正确的,我知道一个标准的Haskell,所有的值都是装箱的,B如@ Shepmaster指出的那样,像递归语言这样的函数可以编译的唯一情况是,不管有多少个内存大小,因此多态的函数变体存储在二进制代码中考虑,WHIC。h对于递归类型,只有通过指针类型等进行间接寻址时,才会出现这种情况。
let mut iter: Box<dyn Iterator<Item = i32>> = Box::new(vec![1, 2, 3].into_iter());
for _ in 0..n {
    iter = Box::new(iter.flat_map(|x| vec![x, x * 2].into_iter()));
}