0

我正在构建一个降价应用程序,我想保留两份文本副本,一份是文本,另一份是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,但我不知道这是否可能。

4

1 回答 1

2

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

如果您调整sourceto的类型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()预期的具有'static生命周期的闭包那样工作,即没有捕获对局部变量的引用的闭包。

于 2017-08-15T23:37:13.447 回答