【问题标题】:Can Rust consume an iterator passed into a function?Rust 可以使用传递给函数的迭代器吗?
【发布时间】:2016-05-23 07:45:50
【问题描述】:

我正在尝试在 Rust 中实现一个简单的 REPL 计算器,但我到处碰壁。

我在遍历硬编码字符串时使用了字符。当我点击一个数字字符时,我想将控制权传递给一个函数,该函数将消耗该数字的其余部分(假设该数字有多个数字)并返回该数字,转换为一个整数。

我在将Chars 迭代器传递给函数时遇到问题。我得到的错误是use of moved value: 'iter'

我知道我不能改变我给其他人的东西——它的所有权已经转移的东西——但我不知道有什么其他的方法可以做到这一点,特别是因为 Chars 迭代器是不可复制的。

#[derive(Clone, Debug)]
enum Token {
    Addition,
    Substraction,
    Multiplication,
    Division,
    Integer(i32),
    Error,
}

fn consume_number(mut iter: std::str::Chars) -> Option<i32> {
    while let Some(item) = iter.next() {
        println!("{:?}", item);
    }

    return Some(1337);
}

fn tokenize(line: &str) -> Vec<Token> {
    let mut iter = line.chars();
    let mut tokens = Vec::new();
    let mut token;

    while let Some(c) = iter.next() {
        if c.is_whitespace() { continue };

        if c.is_digit(10) {
            token = match consume_number(iter) {
                Some(i32) => Token::Integer(i32),
                None => Token::Error,
            };
        } else {
            token = match c {
                '+'                    => Token::Addition,
                '-'                    => Token::Substraction,
                '*'                    => Token::Multiplication,
                '/'                    => Token::Division,
                _                      => Token::Error,
            };
        };
        tokens.push(token);
    }
    return tokens;
}



fn main() {
    let line = "631 * 32 + 212 - 15 / 89";
    println!("{:?}", tokenize(&line));
}

【问题讨论】:

    标签: iterator rust move-semantics ownership-semantics


    【解决方案1】:

    答案是肯定的,它是在FromIterator trait 中完成的。

    您在这里所经历的更为基本:

    fn consume_number(mut iter: std::str::Chars) -> Option<i32> { ... }
    
    while let Some(c) = iter.next() {
        ...
        match_consume_number(iter)
        ...
    }
    

    调用match_consume_number 时,您将迭代器的所有权转移给它。这意味着在循环体的下一次迭代中,这个iter 变量不再可用。

    如果迭代器之后仍然可用,则应传递对它的引用:

    fn consume_number(iter: &mut std::str::Chars) -> Option<i32> { ... }
    
    while let Some(c) = iter.next() {
        ...
        match_consume_number(&mut iter)
        ...
    }
    

    你很接近!

    【讨论】:

    • 非常感谢您,先生!
    • 顺便说一句,你怎么知道问题是迭代器在 while 循环中超出了范围?是什么给了它?我应该一直在寻找什么?
    • use of moved value: 'iter'. 表示iter 的所有权已转移到其他地方。 Rust 中的“移动”意味着“转移所有权”。你会习惯的;)
    • @neektza:iter 并没有“超出范围”,但这是一个不同的概念。当您尝试使用“超出范围”的标识符时,您会收到“未解析的名称”错误。这不是这里发生的事情!
    猜你喜欢
    • 2013-06-03
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 2015-04-15
    • 2014-06-26
    • 2013-09-02
    相关资源
    最近更新 更多