我正在尝试实现一个通用的Cons列表,该列表比本书第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)));
}
Run Code Online (Sandbox Code Playgroud)
(游乐场)
我的代码无法编译,并且有一个令人困惑的消息:
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)));
}
Run Code Online (Sandbox Code Playgroud)
此消息是什么意思?
您有更大的问题。您已经接受了对不可变的特征对象的引用。这意味着您不能调用Iterator::next迭代器上最原始的操作:
impl<T> List<T>
where
T: Debug,
{
fn from_iterable(iterator: &dyn Iterator<Item = T>) -> Self {
iterator.next();
panic!();
}
}
Run Code Online (Sandbox Code Playgroud)
impl<T> List<T>
where
T: Debug,
{
fn from_iterable(iterator: &dyn Iterator<Item = T>) -> Self {
iterator.next();
panic!();
}
}
Run Code Online (Sandbox Code Playgroud)
如果您遵循此错误建议并更新呼叫站点以传递可变引用,则您的代码有效:
impl<T> List<T>
where
T: Debug,
{
fn from_iterable(iterator: &mut dyn 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)));
}
Run Code Online (Sandbox Code Playgroud)
然而,这不是常见的使用对象特点对这种类型的问题,因为它们涉及的动态调度和运行时开销的一些(小)量。取而代之的是,在泛型中使用静态分配更为常见:
impl<T> List<T>
where
T: Debug,
{
fn from_iterable(iterator: impl IntoIterator<Item = T>) -> Self {
iterator
.into_iter()
.fold(List::Nil, |acc, value| List::Cons(value, Box::new(acc)))
}
}
fn main() {
println!("{:?}", List::from_iterable(1..10));
}
Run Code Online (Sandbox Code Playgroud)
我还改用了IntoIterator它,因为它对呼叫者更符合人体工程学。
也可以看看:
| 归档时间: |
|
| 查看次数: |
2455 次 |
| 最近记录: |