簡體   English   中英

Rust:如何在閉包參數中指定生存期?

[英]Rust: How to specify lifetimes in closure arguments?

我正在編寫一個解析器生成器作為學習銹的項目,並且遇到了一些我無法使用生存期和結束時間解決的問題。 這是我的簡化情況(很抱歉,它是如此復雜,但是我需要在實際版本中使用自定義迭代器,這似乎對編譯器的行為有所影響):

游戲圍欄鏈接: http//is.gd/rRm2aa

struct MyIter<'stat, T:Iterator<&'stat str>>{
    source: T
}

impl<'stat, T:Iterator<&'stat str>> Iterator<&'stat str> for MyIter<'stat, T>{
    fn next(&mut self) -> Option<&'stat str>{
        self.source.next()
    }
}

struct Scanner<'stat,T:Iterator<&'stat str>>{
    input: T
}

impl<'main> Scanner<'main, MyIter<'main,::std::str::Graphemes<'main>>>{
    fn scan_literal(&'main mut self) -> Option<String>{
        let mut token = String::from_str("");
        fn get_chunk<'scan_literal,'main>(result:&'scan_literal mut String, 
                                          input: &'main mut MyIter<'main,::std::str::Graphemes<'main>>) 
         -> Option<&'scan_literal mut String>{
            Some(input.take_while(|&chr| chr != "\"")
                 .fold(result, |&mut acc, chr|{
                     acc.push_str(chr);
                     &mut acc
                 }))
        }
        get_chunk(&mut token,&mut self.input);
        println!("token is {}", token);
        Some(token)
    }
}

fn main(){
    let mut scanner = Scanner{input:MyIter{source:"\"foo\"".graphemes(true)}};
    scanner.scan_literal();
}

我在這里知道兩個問題。 首先,我必須在get_chunk函數中隱藏主生命周期(我在impl嘗試過使用它的主生命周期,但是編譯器抱怨'main get_chunk內部未定義get_chunk )。 我認為它仍然可以工作,因為調用后get_chunk將匹配'mainimpl'mainget_chunk ,但我不知道這是正確的。

第二個問題是,閉包內的&mut acc的生存期必須為'scan_literal ,才能像我希望的那樣工作(在此示例中,直到第一個"為止,一直累積字符)。我無法添加顯式生存期但是,對於&mut acc ,編譯器表示其生存期僅限於閉包本身,因此我無法返回引用以在fold的下一次迭代中使用。我已經獲得了以各種其他方式進行編譯和運行的函數,但我不明白這里是什么問題。

我的主要問題是:有沒有辦法明確指定閉包參數的生存期? 如果不是,是否有更好的方法使用fold來累積字符串而不進行多次復制?

首先,關於一生。 在其他函數內部定義的函數是靜態的,它們不以任何方式與其外部代碼連接。 因此,它們的壽命參數是完全獨立的。 您不希望將'main用作get_chunk()的生命周期參數,因為它會get_chunk()外部的'main生命周期,並且只會造成混亂。

接下來,關於閉包。 該表達式:

|&mut acc, chr| ...

很有可能不是您真正認為的那樣。 閉包/函數參數允許使用不可辯駁的模式,並且&在模式中具有特殊含義。 即,它取消引用與之匹配的值,並將其標識符分配給該取消引用的值:

let x: int = 10i;
let p: &int = &x;
match p {
    &y => println!("{}", y)  // prints 10
}

你能想到的&在一個圖案作為相反&中的表達式:在表達它的意思是“需要參考”,在它的意思是“刪除引用”的圖案。

但是mut不屬於&在模式中; 它屬於標識符,表示具有該標識符的變量是可變的,即您不應寫

|&mut acc, chr| ...

|& mut acc, chr| ...

您可能對該RFC感興趣,而該RFC恰恰與此語言語法方面的問題有關。

看來您想做一件非常奇怪的事情,我不確定我了解您的去向。 您很可能混淆不同的字符串類型。 首先,您應該閱讀解釋所有權和借用以及何時使用它們的官方指南 (您可能還想閱讀未完成的所有權指南 ;它將很快進入主文檔樹),然后您應該閱讀字符串指南。

無論如何,您的問題可以通過更簡單,更通用的方式解決:

#[deriving(Clone)]
struct MyIter<'s, T: Iterator<&'s str>> {
    source: T
}

impl<'s, T: Iterator<&'s str>> Iterator<&'s str> for MyIter<'s, T>{
    fn next(&mut self) -> Option<&'s str>{ // '
        self.source.next()
    }
}

#[deriving(Clone)]
struct Scanner<'s, T: Iterator<&'s str>> {
    input: T
} 

impl<'m, T: Iterator<&'m str>> Scanner<'m, T> {  // '
    fn scan_literal(&mut self) -> Option<String>{
        fn get_chunk<'a, T: Iterator<&'a str>>(input: T) -> Option<String> {
            Some(
                input.take_while(|&chr| chr != "\"")
                     .fold(String::new(), |mut acc, chr| {
                         acc.push_str(chr);
                         acc
                     })
            )
        }
        let token = get_chunk(self.input.by_ref());
        println!("token is {}", token);
        token
    }
}

fn main(){
    let mut scanner = Scanner{
        input: MyIter {
            source: "\"foo\"".graphemes(true)
        }
    };
    scanner.scan_literal();
}

您不需要將外部引用傳遞到閉包中。 您可以直接在fold()操作中生成一個String 我還簡化了您的代碼,使其更加慣用。

請注意,現在impl for Scanner也可以與返回&str任意迭代器一起使用。 這很可能是你想寫的不是這個專業Scanner只與工作MyIterGraphemes里面。 by_ref()操作將IIterator<T> &mut I轉換為J ,其中JIterator<T> 即使您只有對原始迭代器的可變引用,它也允許迭代器的進一步鏈接。

順便說一下,您的代碼也不完整。 它只會返回Some("")因為take_while()會停在第一個引號上,並且不會進一步掃描。 您應該重寫它以考慮初始報價。

暫無
暫無

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

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