我试图实现一个通用的缺点列表,比一本书第15章中使用的更为先进:
use std::fmt::Debug;
#[derive(Debug)]
enum List<T> {
Nil,
Cons(T, Box<List<T>>),
}
impl<T> List<T>
where
T: Debug,
{
fn from_iterable(iterator: &Iterator<Item = T>) -> Self {
iterator.fold(List::Nil, |acc, value| List::Cons(value, Box::new(acc)))
}
}
fn main() {
println!("{:?}", List::from_iterable(&(1..10)));
}
我的代码无法编译,它有一个非常令人困惑的消息:
error: the `fold` method cannot be invoked on a trait object
--> src/main.rs:14:18
|
14 | iterator.fold(List::Nil, |acc, value| List::Cons(value, Box::new(acc)))
| ^^^^
这条消息是什么意思?
我已经看到了这个与question有关的东西,但是即使这个是重复的,我目前的知识太有限了,无法连接点。
答案 0 :(得分:4)
你有一个更大的问题。您已接受对不可变的特征对象的引用。这意味着您无法调用Iterator::next
,这是迭代器上最原始的操作:
fn from_iterable(iterator: &Iterator<Item = T>) -> Self {
iterator.next();
panic!();
}
error[E0596]: cannot borrow immutable borrowed content `*iterator` as mutable
--> src/main.rs:14:9
|
13 | fn from_iterable(iterator: &Iterator<Item = T>) -> Self {
| ------------------- use `&mut Iterator<Item = T>` here to make mutable
14 | iterator.next();
| ^^^^^^^^ cannot borrow as mutable
如果您按照此错误建议并更新调用网站以传递可变引用,则代码可以正常运行:
impl<T> List<T>
where
T: Debug,
{
fn from_iterable(iterator: &mut Iterator<Item = T>) -> Self {
iterator.fold(List::Nil, |acc, value| List::Cons(value, Box::new(acc)))
}
}
fn main() {
println!("{:?}", List::from_iterable(&mut (1..10)));
}
但是,对于此类问题使用特征对象是不,因为它们涉及动态调度和一些(小)运行时开销。相反,使用静态调度和泛型更为常见:
impl<T> List<T>
where
T: Debug,
{
fn from_iterable<I>(iterator: I) -> Self
where
I: IntoIterator<Item = T>,
{
iterator
.into_iter()
.fold(List::Nil, |acc, value| List::Cons(value, Box::new(acc)))
}
}
fn main() {
println!("{:?}", List::from_iterable(1..10));
}
我也切换到IntoIterator
,因为它对于来电者来说更符合人体工程学。
另见: