Rust 可以使用传递给函数的迭代器吗?
Can Rust consume an iterator passed into a function?
我正在尝试用 Rust 实现一个简单的 REPL 计算器,但我到处碰壁。
我在迭代硬编码字符串时使用字符。当我点击一个数字字符时,我想将控制权传递给一个函数,该函数将消耗数字的其余部分(假设数字有多个数字)和 return 数字,转换为整数。
我在将 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));
}
答案是肯定的,是在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)
...
}
你很接近!
我正在尝试用 Rust 实现一个简单的 REPL 计算器,但我到处碰壁。
我在迭代硬编码字符串时使用字符。当我点击一个数字字符时,我想将控制权传递给一个函数,该函数将消耗数字的其余部分(假设数字有多个数字)和 return 数字,转换为整数。
我在将 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));
}
答案是肯定的,是在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)
...
}
你很接近!