Может ли Rust использовать итератор, переданный в функцию?

Я пытаюсь реализовать простой калькулятор REPL в Rust, и я бью кирпичные стены повсюду.

Я потребляю символы, перебирая жестко закодированную строку. Когда я нажимаю числовой символ, я хочу передать управление функции, которая будет использовать оставшуюся часть числа (при условии, что число имеет более одной цифры) и вернет число, преобразованное в целое число.

У меня проблемы с прохождением 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));
}

1 ответ

Решение

Ответ - да, это сделано в FromIterator черта характера.

То, что вы испытываете здесь, является гораздо более простым:

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)
    ...
}

Вы были близки!

Другие вопросы по тегам