我正在尝试实现Tree
结构,但是每当尝试运行以下代码时,我都会不断收到错误消息:
fn main() {
let tree = Tree::create(1, |_| Vec::new());
println!("{:?}", tree);
}
#[derive(Debug)]
struct Tree<T> {
value: T,
children: Vec<Tree<T>>,
}
impl<T> Tree<T> {
fn create<F>(value: T, get_children: F) -> Tree<T>
where
F: Fn(&T) -> Vec<T>,
{
let children = get_children(&value);
Tree {
value,
children: children
.into_iter()
.map(|x| Tree::create(x, |y| get_children(y)))
.collect(),
}
}
}
错误:
error: reached the type-length limit while instantiating `<std::vec::IntoIter<i32> as std::iter::Iterator>::map::<Tree<i32...`
|
= note: consider adding a `#![type_length_limit="2097152"]` attribute to your crate
答案 0 :(得分:1)
您在创建Tree<T>
时正在进行递归调用:
impl<T> Tree<T> {
fn create<F>(value: T, get_children: F) -> Tree<T>
//...
//...
.map(|x| Tree::create(x, |y| get_children(y))) //endless recursive call
我很困惑为什么自从我返回一个空后就无限递归 封闭中的向量。
此错误在编译过程中发生,并且错误表明为reached the type-length limit while instantiating...
。这意味着您正在生成一个非常长的类型。
调用Tree::create(x, |y| get_children(y))
时,您正在创建一个参数闭包,该闭包将调用现有闭包。没关系,但是当您递归调用它时,编译器将无法在最内部的调用中检测到F
的类型。
记住get_children
的类型为F
,其中F: Fn(&T) -> Vec<T>
。
首次调用Tree::create
时,将像这样推断出F
中的create<F>
:
let tree = Tree::create(1, |_| Vec::new());
//inference of F: Fn(&T) -> Vec<T>
在map(...)
中第二次通话后:
Tree::create(x, |y| get_children(y))
//inference of F: Fn(&T) -> Fn(&T) -> Vec<T>
然后它将最终变成:
//inference of F: Fn(&T)-> Fn(&T) -> Fn(&T) -> Vec<T>
//inference of F: Fn(&T)-> ... -> Fn(&T) -> Fn(&T) -> Vec<T>
最后,编译器达到了类型长度限制。
除了Shepmaster's answer之外,您还可以使用function pointers:
impl<T> Tree<T> {
fn create(value: T, get_children: fn(&T) -> Vec<T>) -> Tree<T> {
let children = get_children(&value);
Tree {
value,
children: children
.into_iter()
.map(|x| Tree::create(x, get_children))
.collect(),
}
}
}
您可以通过将函数作为Vec<Tree<T>>
发送到get_children
而不是像这样在create
中生成函数来解决此问题:
fn main() {
let inner_tree = Tree::create(1, |_| Vec::new());
let tree = Tree::create(1, move |_| vec![inner_tree]);
println!("{:?}", tree);
}
#[derive(Debug)]
struct Tree<T> {
value: T,
children: Vec<Tree<T>>,
}
impl<T> Tree<T> {
fn create<F>(value: T, get_children: F) -> Tree<T>
where
F: FnOnce(&T) -> Vec<Tree<T>>,
{
let children = get_children(&value);
Tree { value, children }
}
}
请注意,我将函数参数的类型从Fn
更改为FnOnce
。需要将内部树的所有权移至闭包中。它将被调用一次,以便可以使用该变量。
答案 1 :(得分:1)
这是与What does "Overflow evaluating the requirement" mean and how can I fix it?相同的潜在问题,可以用相同的方法解决。这意味着您可以通过使用引用特征对象来避免类型级别的递归:
impl<T> Tree<T> {
fn create(value: T, mut get_children: impl FnMut(&T) -> Vec<T>) -> Tree<T> {
fn create_inner<T>(value: T, get_children: &mut FnMut(&T) -> Vec<T>) -> Tree<T> {
let children = get_children(&value)
.into_iter()
.map(|x| create_inner(x, get_children))
.collect();
Tree { value, children }
}
create_inner(value, &mut get_children)
}
}
我也从Fn
切换到FnMut
,因为在可能的情况下使用闭包类型更好些。