簡體   English   中英

如何使用 Rust 的 Peekable?

[英]How to use Rust's Peekable?

我有興趣在字符流中提前查看。 據我了解, 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

有人可以解釋一下:

  • 為什么 Peekable 由於缺乏特性而不能出現在函數類型中,
  • 編譯器說“移出取消引用”和
  • 我如何解決其中一個或兩個?

第三個版本

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

我無法理解 rust 在這里對我說的是什么,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();
    …
}

還要注意peekable()方法按值獲取 self ; 你不能對那里的迭代器進行可變引用。

您的目標是替代方案,但我通常不太傾向於這樣做,那就是要求參數是可窺視的,將負擔推給調用者,就像您所做的那樣:

fn trawl<I, E>(pk: Peekable<E, I>) where I: Iterator<Result<char, E>> {
    …
}

Peekable實際上是一個結構體,而不是特征。 如果你想要一個Peekable ,你可以像這樣定義你的函數:

fn trawl<E, I>(it: Peekable<I>) where I: Iterator<Result<char, E>> {
    ...
}

您的第二個實現無法編譯,因為peek按值獲取self (即它消耗迭代器,返回一個新的迭代器),因此您不能通過&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

就風格而言,我會說第二種形式是更好的方法,因為第一種形式泄露了基本上是實現細節的內容。

自從之前的答案以來,Rust 已經發生了一些變化。 現在的做法是:

fn trawl<I, E>(pk: Peekable<I>) 
where I: Iterator<Item = Result<char, E>> {
    …
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM