【发布时间】:2018-05-25 18:32:19
【问题描述】:
我有几个解析器。有一个顶级的可以委托给另一个。
Parsers 从Reader(可变)获取输入。我希望一次只能解析一个Parser,只有一个解析器应该有Reader。
我通过为顶级解析器创建一个枚举来做到这一点,该解析器要么是读取器,要么是委托解析器(具有读取器)。这样它只能在未授权时读取,这就是我想要的。
从顶级解析器,我需要可变地借用这个枚举来确定要做什么并获得阅读器或委托解析器。问题是,如果我想开始或停止委派,我需要移动Reader。但此时它仍然是可变借用的。
我创建了一个最小的示例,并包含了 cmets 关于 replace 和非词法生命周期的建议:
#![feature(nll)]
use std::mem::replace;
struct Reader {
i: u8,
}
impl Reader {
fn next(&mut self) -> u8 {
/* some logic here */
self.i += 1;
self.i
}
}
trait Parser {
fn parse(&mut self) -> u8;
}
enum ReaderOrDelegate {
Read(Reader),
Delegate(AnotherParser), /* Trait object in reality, but keeping it simple here. */
}
struct OneParser {
reader_or_delegate: ReaderOrDelegate,
}
impl Parser for OneParser {
fn parse(&mut self) -> u8 {
match self.reader_or_delegate {
ReaderOrDelegate::Delegate(ref mut delegate) => {
match delegate.parse() {
0 => {
replace(&mut self.reader_or_delegate, ReaderOrDelegate::Read(delegate.consume()));
self.parse()
},
x => 2 * x
}
},
ReaderOrDelegate::Read(ref mut reader) => {
match reader.next() {
0 => {
replace(&mut self.reader_or_delegate, ReaderOrDelegate::Delegate(AnotherParser { reader }));
self.parse()
},
x => 3 * x
}
},
}
}
}
struct AnotherParser {
reader: Reader,
}
impl AnotherParser {
fn consume(self) -> Reader {
self.reader
}
}
impl Parser for AnotherParser {
fn parse(&mut self) -> u8 {
self.reader.next() * 2
}
}
有了评论建议,还有一个错误:
error[E0308]: mismatched types
--> src/main.rs:42:106
|
42 | replace(&mut self.reader_or_delegate, ReaderOrDelegate::Delegate(AnotherParser { reader }));
| ^^^^^^ expected struct `Reader`, found &mut Reader
|
= note: expected type `Reader`
found type `&mut Reader`
我相信我可以通过从ReaderOrDelegate 中取出reader 并将其作为Rc<RefCell<Parser>>> 放入每个解析器中来解决这个问题。但我认为将它放在枚举中更合乎逻辑:一次应该只有一个解析器能够使用阅读器。这可能吗?
我知道这些错误在这种情况下是有道理的,但我觉得从高层次上讲,应该可以做我想做的事。 Reader 只需要一个所有者。
编辑:对我来说,replace 的问题如何通过“嵌套”应用于这种情况(reader 已经被match 借用然后想要交换一个字段)。因此,虽然可能相关,但我认为另一个问题不足以解决这个问题。反正不适合我。
EDIT 2:在代码示例和错误中包含评论建议。
【问题讨论】:
-
我认为这是重复的。如果你想使用
struct的字段,你也必须使用struct(否则它会有一个带有“损坏”内存的字段) -
必须有某种限制或解决方法,对吧?否则每次使用任何字段时都会消耗整个对象结构。
-
想一想:如何在不移动整个结构的情况下移动字段?
-
感谢
replace的提示,我尝试改用replace(&mut self.reader_or_delegate, ReaderOrDelegate::Delegate(AnotherParser { reader }));。但问题仍然存在:我无法创建AnotherParser,因为reader已被match借用。
标签: delegates rust pattern-matching borrow-checker ownership