Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 在多个';静态闭包_Rust - Fatal编程技术网

Rust 在多个';静态闭包

Rust 在多个';静态闭包,rust,Rust,给定一个使用回调将事件传递给库用户的库(例如GUI库),我如何在程序中获得适当的可变性?例如: // so I have this `obj` I want to modify when the user clicks buttons // in the GUI let same_action = move |_| { // modify obj in several ways, e.g. obj.text = "Modified" obj.text = "Modified"; } /

给定一个使用回调将事件传递给库用户的库(例如GUI库),我如何在程序中获得适当的可变性?例如:

// so I have this `obj` I want to modify when the user clicks buttons
// in the GUI

let same_action = move |_| {
  // modify obj in several ways, e.g. obj.text = "Modified"
  obj.text = "Modified";
}
// --> I had to move `obj` above since `on_click` has a `'static`
// constraint for `F` but that's not really a thing I want to do,
// I want to keep control of `obj` in the outer scope!!!

// --> error because `same_action` does not implement `Fn` since it
// mutates the moved `obj` in it
button1.on_click(same_action);
// --> if the above worked, here we'd have a error because `button1`
// has moved `same_action`
button2.on_click(same_action);
// --> assuming all of the above worked, we'd have a error here about
// unable to use `obj` because it has been moved to same_action
button3.on_click(move |_| obj.text = "Another modifier");

// the library now process the gui and call the callbacks in a loop
// until exit
gui_run();

// --> ..., error cannot use `obj` because it has been moved by
// `same_action`
println!("Final value: {}", obj.text);
有关此问题的关键点,请参见带有
/-->
的注释

这似乎是Rust中事件驱动API的常见问题。
你是如何解决这个问题的?

如果你需要共享可变数据,你需要一些容器来确保遵循别名规则,最有可能的是来自一个容器。对于
Copy
数据,这是
Cell
,对于其他类型,则是
RefCell
。然后,闭包可以使用以下任一方法:

  • 单元格
    /
    单元格
    ,或
  • object
    中的一些字段是
    Cell
    s和
    RefCell
    s
哪一个更好取决于您希望可变性的粒度,以及这是
object
的所有用户的共同需求,还是仅针对这个特定的闭包。在第二种情况下,您需要更改对象的定义,在第一种情况下,您可以执行以下操作:

let obj = RefCell::new(obj);

let same_action = move |_| {
  obj.borrow_mut().text = "Modified";
}
如果您还不能在闭包的捕获值中使用借词,例如由于
静态
绑定,您可以将
RefCell
放入
Rc


此外,您不能将相同的操作传递给两个按钮,因为不能复制或克隆闭包。一般来说,这是不可能的,因为它们可能会关闭无法复制或克隆的东西。如果可能的话,将来可能会允许这样做,因为现在你可以用一个宏、一个函数(必须将闭包装箱)来解决这个问题,或者如果简单的话,只需写两次闭包。

你有什么样的保护措施来防止并发变异?其他事件驱动API如何处理并发变异引起的争用?@Shepmaster并发是不允许的,即它保证回调将在与
gui\u run
相同的线程中调用。我认为它甚至不允许从主线程以外的其他线程使用API。并发性甚至不重要。一个线程中的两个别名
&mut
s(或者甚至只有一个
&mut
和一个
&
)足以让您陷入困境,例如迭代无效。关于单元格类型的好观点,但是代码注释中指出的问题仍然存在,因为
RefCell
obj
已被移动到
相同的动作中(不能将其视为
&
,因为约束中的静态生存期
F:Fn(…)+'static
),因此,它不能在外部范围中使用,也不能在
按钮3
回调中使用。加上另一个事实,即
相同的动作
不能被使用两次(在
按钮1
按钮2
)在回答中是受欢迎的。@2012年,我想我现在已经解决了这个问题。哦,
Rc
,很好,这使它起作用了,谢谢!在每次关闭之前,让x=rc.clone()
我必须做些什么?而且,我不是在一个性能关键型系统上,只是出于好奇,因为
Rc
似乎是Rust中的常见模式,
Rc
执行动态分配考虑到Rust打算用于性能关键型系统,这种动态分配不是一件坏事吗?@TheLink 2012
Rc
(或普通的
Rc
)只在必要时使用。如果有必要,那么……你可能无论如何都无法避免分配,或者不容易避免。生锈允许你避免分配和其他昂贵的东西,你仍然有责任决定是否值得。