这是一个更高级别的问题,但是我不确定应该使用Rust的哪些功能来改进问题。
在编写具有工具 API的图形应用程序的第一步时,我们可能希望传入context
参数,该参数公开应用程序的各个部分:
// Where the data lives.
struct Application {
preferences: Preferences,
windows: Vec<Windows>,
documents: Vec<Document>,
}
// A view on the data to pass to tool-code.
struct AppContext {
preferences: &Preferences, // immutable
window: &Window, // immutable
doc: &Document, // mutable
// ... real world use case has more vars ...
}
// example use
fn some_tool_uppercase(context: &mut AppContext, options: &ToolOptions) {
// random example
for w in context.document.words {
w.to_uppercase();
}
context.window.redraw_tag();
}
写这篇文章的时候,我遇到了借用检查器的问题,因为文档也存储在其他文档的列表中 - 导致它一次在两个地方变异。
只是让我的程序编译,目前我正在从列表中删除文档,运行该工具,然后在工具完成时将其添加回文档列表。
虽然在某些情况下可以传递多个参数,但上面的示例已经简化了。将上下文的每个成员作为参数传递是不切实际的。
如何将应用程序的上下文包装到可以传递到工具代码中的类型中,而不会导致借用检查器的复杂化?
答案 0 :(得分:0)
&
用于临时向函数借用数据。通常,当您需要访问代码中多个位置的数据时,您需要Rc
或Arc
类型。
此外,您可能希望数据具有内部可变性。在这种情况下,您还需要将其包装在Cell
或RefCell
。
如果你的数据是在线程之间共享的,你还需要用Mutex
或RwLock
来包装它。
现在,根据您的使用情况,您需要在数据结构中复合所有这些内容。有关更多信息,请阅读:rust wrapper type composition
您的示例可能如下所示:
// Where the data lives.
struct Application {
preferences: Rc<Preferences>,
windows: Rc<Vec<Windows>>,
document: Rc<RefCell<Vec<Document>>>,
}
// A view on the data to pass to tool-code.
struct AppContext {
preferences: Rc<Preferences>, // immutable
window: Rc<Window>, // immutable
document: Rc<RefCell<Document>>, // mutable
// ... real world use case has more vars ...
}
// example use
fn some_tool_uppercase(context: &mut AppContext, options: &ToolOptions) {
// random example
for w in (*context.document.borrow_mut()).words {
w.to_uppercase();
}
context.window.redraw_tag();
}
或者它是多线程的:
struct Application {
preferences: Arc<RwLock<Preferences>>,
windows: Arc<Mutex<Vec<Windows>>>,
document: Arc<Mutex<Vec<Document>>,
}
....