我有兴趣在角色流中偷看.根据我的理解,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());
}
Run Code Online (Sandbox Code Playgroud)
这无法编译
> 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
Run Code Online (Sandbox Code Playgroud)
好的,公平的.我还没有完全理解特征所以我尝试传递一个迭代器,然后创建一个可窥探的版本:
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());
}
Run Code Online (Sandbox Code Playgroud)
这失败了
> 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
Run Code Online (Sandbox Code Playgroud)
有人能解释一下:
第三个版本
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());
}
Run Code Online (Sandbox Code Playgroud)
这失败了:
> 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
Run Code Online (Sandbox Code Playgroud)
我不明白生锈在这里对我说什么,Iterator.next将如何从Peekable.peek获得不同的返回类型.
Peekable不是一个特征,因此不能用作约束,这表明它可能意味着许多类型中的一种.它是一种单一的,具体的,具体的类型struct Peekable<A, T>.正如您所观察到的,它是通过peekable()在迭代器上调用该方法来构造的,该迭代器将其更改为可窥探的内容.
如果您只是想使用迭代器,那么您可以使用它:
fn trawl<I, E>(iter: I) where I: Iterator<Result<char, E>> {
let pk = pk.peekable();
…
}
Run Code Online (Sandbox Code Playgroud)
另请注意,该peekable()方法采用自值; 你不能在那里对一个迭代器进行可变引用.
你所瞄准的另一种选择,但我通常不太倾向于这种选择,就是要求论证是可以窥视的,把负担放在打电话上,就像你有:
fn trawl<I, E>(pk: Peekable<E, I>) where I: Iterator<Result<char, E>> {
…
}
Run Code Online (Sandbox Code Playgroud)
小智 6
Peekable实际上是一个结构,而不是一个特征.如果你想要a Peekable,你可以像这样定义你的函数:
fn trawl<E, I>(it: Peekable<I>) where I: Iterator<Result<char, E>> {
...
}
Run Code Online (Sandbox Code Playgroud)
你的第二个实施无法编译,因为peek需要self通过值(即它消耗的迭代器,返回一个新的),这样你就可以不通过调用它&mut的参考.大多数代码只是通过值而不是引用来获取迭代器:
fn trawl<E, I>(it: I) where I: Iterator<Result<char, E>> {
let it = it.peekable();
...
}
Run Code Online (Sandbox Code Playgroud)
如果您不想将迭代器移动到类似函数中trawl,则可以使用该by_ref()方法创建一个保留在&mut引用上的新迭代器:
let mut my_iterator = /* whatever */;
trawl(my_iterator.by_ref());
// my_iterator is still usable here
Run Code Online (Sandbox Code Playgroud)
就风格而言,我会说第二种形式是更好的方式,因为第一种方式泄漏的基本上是一个实现细节.
自之前的答案以来,Rust 发生了一些变化。现在的做法是:
\n\nfn trawl<I, E>(pk: Peekable<I>) \nwhere I: Iterator<Item = Result<char, E>> {\n \xe2\x80\xa6\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
4178 次 |
| 最近记录: |