Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 强制字段共享生存期_Rust - Fatal编程技术网

Rust 强制字段共享生存期

Rust 强制字段共享生存期,rust,Rust,我用的是Rust 0.13,我对Rust还比较陌生。 我有一个结构想要拥有一个字符串输入,但我有一个代码想要处理该字符串的片段,工作 pub struct Lexer<'a> { input : Option<String>, work : &'a str, ... } 我将其解释为,self.input可能会更改,从而使self.work的视图无效。 这是合理的解释吗 有没有办法指定这些字段以某种方式相互关联? 我想,如果我能指定Lex

我用的是Rust 0.13,我对Rust还比较陌生。 我有一个结构想要拥有一个字符串
输入
,但我有一个代码想要处理该字符串的片段,
工作

pub struct Lexer<'a> {
    input : Option<String>,
    work : &'a str,
    ...
}
我将其解释为,
self.input
可能会更改,从而使
self.work
的视图无效。 这是合理的解释吗

有没有办法指定这些字段以某种方式相互关联? 我想,如果我能指定
Lexer.input
为final,这将起作用,但Rust似乎没有办法做到这一点

编辑:示例调用代码

let mut lexer = lex::Lexer::new();

lexer.add("[0-9]+", Token::NUM);
lexer.add("\\+", Token::PLUS);

for line in io::stdin().lock().lines() {
    match line {
        Ok(input) => {
            lexer.input(input.as_slice());
            lexer.lex();
        },
        Err(e) => ()
    }
}

我认为你的问题可以通过增加一层来解决。您可以有一个层来收集lexer的规则,然后创建一个新的结构来实际执行lexer。这与Rust中的迭代器是如何实现的是平行的

struct MetaLexer<'a> {
    rules: Vec<(&'a str, u32)>,
}

impl<'a> MetaLexer<'a> {
    fn new() -> MetaLexer<'a> { MetaLexer { rules: Vec::new() } }

    fn add_rule(&mut self, name: &'a str, val: u32) {
        self.rules.push((name, val));
    }

    fn lex<'r, 's>(&'r self, s: &'s str) -> Lexer<'a, 's, 'r> {
        Lexer {
            rules: &self.rules,
            work: s,
        }
    }
}

struct Lexer<'a : 'r, 's, 'r> {
    rules: &'r [(&'a str, u32)],
    work: &'s str,
}

impl<'a, 's, 'r> Iterator for Lexer<'a, 's, 'r> {
    type Item = u32;

    fn next(&mut self) -> Option<u32> {
        for &(name, val) in self.rules.iter() {
            if self.work.starts_with(name) {
                self.work = &self.work[name.len()..];
                return Some(val);
            }
        }

        None
    }
}

fn main() {
    let mut ml = MetaLexer::new();
    ml.add_rule("hello", 10);
    ml.add_rule("world", 3);

    for input in ["hello", "world", "helloworld"].iter() {
        // So that we have an allocated string,
        // like io::stdin().lock().lines() might give us
        let input = input.to_string(); 

        println!("Input: '{}'", input);
        for token in ml.lex(&input) {
            println!("Token was: {}", token);
        }
    }
}
struct MetaLexer,
}
恳求{
fn new()->MetaLexer Lexer{
项目类型=u32;
fn下一步(&mut self)->选项{
对于self.rules.iter()中的&(name,val){
如果self.work.以(名称)开头{
self.work=&self.work[name.len()…];
返回一些(val);
}
}
没有一个
}
}
fn main(){
让mut ml=MetaLexer::new();
ml.add_规则(“hello”,10);
ml.add_规则(“世界”,3);
用于输入[“hello”、“world”、“helloworld”].iter(){
//这样我们就有了一个分配的字符串,
//比如io::stdin().lock().lines()可能会给我们
让input=input.to_string();
println!(“输入:'{}',输入);
对于ml.lex中的令牌(&input){
println!(“令牌是:{}”,令牌);
}
}
}
实际上,您可以重命名
MetaLexer
->
Lexer
Lexer
->
LexerItems
,然后您将真正匹配标准库中的迭代器


如果您的问题是我如何保留从stdin读取的数据的引用,这是一个不同的问题,与您的原始陈述相去甚远。

可能重复“如果我可以指定Lexer.input为final”-如果你想要一个永远不会改变的字符串,那听起来像是一个
&str
^^。我同意这一点,但我真的不知道如何处理
字符串
备份
输入:&str
。我发现这样做会把我的
Lexer
与它的
输入绑定在同一个生命周期,所以我想我不知道我是怎么用C语言写的,然后改用这种方式,“这种方式最终把我的Lexer和我的生活绑在了一起”-是的,你想让你的Lexer与
&str
绑定到同一个生命周期-这是Rust唯一能确保你不会对不再存在的字符串进行Lexer,并且它不会在你下面发生变化的方法。这就是为什么我试图将输入移动到
Lexer
,让我使用Rust试图提供的不变量。用于考试例如,我可能想调用
Lexer.input()
在来自
stdin
的多个不同输入上,但如果我使用
&str
这样做,我不知何故需要
stdin
中的字符串与lexer结构具有相同的作用域,这似乎不可行,或者在内存使用方面根本不符合我的要求。因此,我基本上是使用工厂来计算生命周期正确地说。我喜欢。你知道有一个引用谈到“如何保存从stdin读取的数据的引用”吗?我没有注意到任何类似的引用不是指过时的版本,尽管我可能没有应用
.clone()
创意十足。@mattbreant我没有任何直接的参考资料,但我有一些想法可以用来回答一个新问题。然后你也会得到其他人的想法。
let mut lexer = lex::Lexer::new();

lexer.add("[0-9]+", Token::NUM);
lexer.add("\\+", Token::PLUS);

for line in io::stdin().lock().lines() {
    match line {
        Ok(input) => {
            lexer.input(input.as_slice());
            lexer.lex();
        },
        Err(e) => ()
    }
}
struct MetaLexer<'a> {
    rules: Vec<(&'a str, u32)>,
}

impl<'a> MetaLexer<'a> {
    fn new() -> MetaLexer<'a> { MetaLexer { rules: Vec::new() } }

    fn add_rule(&mut self, name: &'a str, val: u32) {
        self.rules.push((name, val));
    }

    fn lex<'r, 's>(&'r self, s: &'s str) -> Lexer<'a, 's, 'r> {
        Lexer {
            rules: &self.rules,
            work: s,
        }
    }
}

struct Lexer<'a : 'r, 's, 'r> {
    rules: &'r [(&'a str, u32)],
    work: &'s str,
}

impl<'a, 's, 'r> Iterator for Lexer<'a, 's, 'r> {
    type Item = u32;

    fn next(&mut self) -> Option<u32> {
        for &(name, val) in self.rules.iter() {
            if self.work.starts_with(name) {
                self.work = &self.work[name.len()..];
                return Some(val);
            }
        }

        None
    }
}

fn main() {
    let mut ml = MetaLexer::new();
    ml.add_rule("hello", 10);
    ml.add_rule("world", 3);

    for input in ["hello", "world", "helloworld"].iter() {
        // So that we have an allocated string,
        // like io::stdin().lock().lines() might give us
        let input = input.to_string(); 

        println!("Input: '{}'", input);
        for token in ml.lex(&input) {
            println!("Token was: {}", token);
        }
    }
}