У меня есть простой парсер, который можно преобразовать в нечто вроде этого:
use std::str::Chars;
use std::iter::Peekable;
struct Parser<'a> {
input: Peekable<Chars<'a>>,
}
impl<'a> Parser<'a> {
fn new(input: &'a str) -> Self {
Parser {
input: input.chars().peekable(),
}
}
fn consume(&mut self, check: char) -> bool {
// see below
}
}
Моя первоначальная реализация consume
, которая должна смотреть на следующий символ во входных данных и возвращать true (и продвигать Peekable
), если он соответствует переданному символу, была такой:
fn consume(&mut self, check: char) -> bool {
match self.input.peek() {
Some(c) if *c == check => {
self.input.next();
true
},
_ => false
}
}
Компилятор сообщил мне, что я не могу заимствовать self.input
для вызова next
, поскольку я уже заимствовал его в вызове peek
:
error[E0499]: cannot borrow `self.input` as mutable more than once at a time
--> src/main.rs:18:17
|
16 | match self.input.peek() {
| ---------- first mutable borrow occurs here
17 | Some(c) if *c == check => {
18 | self.input.next();
| ^^^^^^^^^^ second mutable borrow occurs here
...
22 | }
| - first borrow ends here
Я не понимаю, почему добавление &
к выражению соответствия Some
(и удаление *
из *c
) приводит к компиляции кода:
fn consume(&mut self, check: char) -> bool {
match self.input.peek() {
Some(&c) if c == check => {
self.input.next();
true
},
_ => false
}
}
Основываясь на комментарии Боэтиоса, каким было бы правильное решение, если бы c
не было Copy
?
Some(&c)
вы удаляете ссылку и делаете копию символа. СSome(c)
вы сохраняете ссылку на него, что предотвращает повторное заимствование. - person Boiethios   schedule 19.12.2017c
не было отмеченоCopy
? - person Michelle Tilley   schedule 19.12.2017let has_matched = /*etc.*/
и после блокаmatch
:if has_matched { self.input.next() }
. Когда вы застряли, промежуточная переменная часто является хорошим решением. - person Boiethios   schedule 19.12.2017