【问题标题】:How to set a variable inside a gtk-rs closure?如何在 gtk-rs 闭包中设置变量?
【发布时间】:2018-01-23 22:06:19
【问题描述】:

我正在构建一个降价应用程序,我想保留两份文本副本,一份是 source 文本,另一份是 TextBuffer 以及所有正确的标签等。

我需要在闭包内设置这个源字段的内容:

buffer.connect_begin_user_action(clone!(source => move |a| {
  let text = a.get_text(&a.get_start_iter(), &a.get_end_iter(), false).unwrap();
  source = text; // error: cannot assign to captured outer variable in an `Fn` closure

另一种方法可能是在TextBuffer 上设置一些属性,但我不知道这是否可行。

【问题讨论】:

  • 为什么你认为使用这个库会改变其他语言的语义和规则?换句话说,为什么你认为使用 gtk-rs 很重要?这是否可以作为“如何在 Rust 闭包中设置变量”的假设问题的副本而关闭?
  • 我不确定将问题重命名为什么。

标签: rust gtk-rs


【解决方案1】:

TextBufferExt::connect_begin_user_action() 接受Fn-closures,即不能更改其捕获环境的闭包。当您需要更改无法更改的内容时,可以使用具有内部可变性的类型,例如 RefCell

如果您将source 的类型调整为RefCell<String> 并将闭包内的赋值更改为*source.borrow_mut() = text;,代码将编译,但还有另一个问题。您为克隆的source 分配一个值。

clone! 扩展为

{
    let source = source.clone();
    move |a| {
       let text = // ...
       // ...
    }
}

也就是说,闭包捕获并更改了变量source 的副本,而不是原始变量。 Rc 是做你想做的事情的方法之一

use std::cell::RefCell;
use std::rc::Rc;
// ...
let source = Rc::new(RefCell::new("Text".to_string()));
// ...
buffer.connect_begin_user_action(clone!(source => move |a| {
    let text = a.get_text(&a.get_start_iter(), &a.get_end_iter(), false).unwrap();
    *source.borrow_mut() = text;
    // ...
}));

另一种方法是删除clone! 宏并通过引用捕获source(您需要在关闭之前删除move),但在这种情况下它不会起作用,因为connect_begin_user_action() 期望使用@987654337 关闭@lifetime,这是一个没有捕获对局部变量的引用的闭包。

【讨论】:

  • 非常感谢,就是这样!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多