我有兴趣在角色流中偷看。根据我的理解,Peekable将是最佳选择。我无法完全弄清楚如何使用它。
首次尝试:
fn trawl<I, E>(pk: &mut I) where I: std::iter::Peekable<Result<char, E>> {
loop {
let cur = pk.next();
let nxt = pk.peek();
match (cur, nxt) {
(Some(i), Some(nxt_i)) => println!("{} {}", i.ok(), nxt_i.ok()),
_ => (),
}
}
}
fn main() {
trawl(&mut std::io::stdio::stdin().chars());
}
无法使用
进行编译> rustc /tmp/main.rs
/tmp/main.rs:1:37: 1:73 error: `std::iter::Peekable` is not a trait
/tmp/main.rs:1 fn trawl<I, E>(pk: &mut I) where I: std::iter::Peekable<Result<char, E>> {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
好的,够公平的。我还没有完全理解特征,所以我尝试传递一个迭代器,然后创建一个可窥探的版本:
fn trawl<I, E>(it: &mut I) where I: Iterator<Result<char, E>> {
let mut pk = it.peekable();
loop {
let cur = pk.next();
let nxt = pk.peek();
match (cur, nxt) {
(Some(i), Some(nxt_i)) => println!("{} {}", i.ok(), nxt_i.ok()),
_ => (),
}
}
}
fn main() {
trawl(&mut std::io::stdio::stdin().chars().peekable());
}
失败
> rustc /tmp/main.rs
/tmp/main.rs:2:18: 2:20 error: cannot move out of dereference of `&mut`-pointer
/tmp/main.rs:2 let mut pk = it.peekable();
^~
/tmp/main.rs:7:65: 7:70 error: cannot move out of dereference of `&`-pointer
/tmp/main.rs:7 (Some(i), Some(nxt_i)) => println!("{} {}", i.ok(), nxt_i.ok()),
^~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
/tmp/main.rs:7:39: 7:77 note: expansion site
error: aborting due to 2 previous errors
有人可以解释一下:
第三个版本
fn trawl<I, E>(mut it: I) where I: Iterator<Result<char, E>> {
let mut pk = it.peekable();
loop {
let cur = pk.next();
let nxt = pk.peek();
match (cur, nxt) {
(Some(i), Some(nxt_i)) => println!("{} {}", i.ok(), nxt_i.ok()),
// (Some(i), ) => println!("{}", i.ok()),
_ => (),
}
}
}
fn main() {
trawl(std::io::stdio::stdin().chars().peekable());
}
这失败了:
> rustc /tmp/main.rs
/tmp/main.rs:7:65: 7:70 error: cannot move out of dereference of `&`-pointer
/tmp/main.rs:7 (Some(i), Some(nxt_i)) => println!("{} {}", i.ok(), nxt_i.ok()),
^~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
/tmp/main.rs:7:39: 7:77 note: expansion site
error: aborting due to previous error
我无法理解生锈在这里对我说什么,Iterator.next将如何从Peekable.peek获得不同的返回类型。
答案 0 :(得分:6)
Peekable
不是特征,因此不能用作绑定,这表明它可能意味着许多类型中的一种。它是一种特定的具体类型struct Peekable<A, T>
。正如您所观察到的,它是通过在迭代器上调用peekable()
方法构造的,该方法将其更改为可以窥视的内容。
如果您只是想使用迭代器,那么您可以使用它:
fn trawl<I, E>(iter: I) where I: Iterator<Result<char, E>> {
let pk = pk.peekable();
…
}
另请注意peekable()
方法取值为self;你不能在那里对迭代器进行可变引用。
你所瞄准的另一种选择,但我通常不太倾向于这种选择,就是要求论证是可以窥视的,把负担放在打电话上,就像你一样:
fn trawl<I, E>(pk: Peekable<E, I>) where I: Iterator<Result<char, E>> {
…
}
答案 1 :(得分:5)
Peekable
实际上是一个结构,而不是一个特征。如果你想要Peekable
,你可以像这样定义你的函数:
fn trawl<E, I>(it: Peekable<I>) where I: Iterator<Result<char, E>> {
...
}
您的第二个实现无法编译,因为peek
按值self
获取(即消耗迭代器,返回一个新的迭代器),因此您可以&#39;通过&mut
引用来调用它。大多数代码只是通过值而不是引用来获取迭代器:
fn trawl<E, I>(it: I) where I: Iterator<Result<char, E>> {
let it = it.peekable();
...
}
如果您不想将迭代器移动到trawl
之类的函数中,可以使用by_ref()
方法创建一个保留&mut
引用的新迭代器:
let mut my_iterator = /* whatever */;
trawl(my_iterator.by_ref());
// my_iterator is still usable here
就风格而言,我会说第二种形式是更好的方式,因为第一种方式泄漏的基本上是实施细节。
答案 2 :(得分:1)
自上次回答以来,铁锈已经改变了一点。现在要做的是:
fn trawl<I, E>(pk: Peekable<I>)
where I: Iterator<Item = Result<char, E>> {
…
}