如何在方法中调用闭包

时间:2016-08-22 12:29:44

标签: rust

我尝试从结构do_something实施的method A调用闭包。我读了一些关于此的帖子,但我现在有点迷失了。这是一个简化版本:

// A simple structure
struct A<F> {
    f: F,
}

// Implements new and do_something
impl<F> A<F> where F: Fn() {
    fn new(f: F) -> A<F> {
        A { f: f }
    }
    fn do_something(&self) {
        self.f() // Error is here.
    }
}

fn main() {
    let a = A::new( || println!("Test") );
    a.do_something()
}

显示以下错误:

  

错误:在当前范围

中找不到类型f的名为&A<F>的方法

我认为闭包被称为just like this,但似乎我错过了一些东西。我尝试用self.f()替换self.f.call()(没有真正理解的随机测试),但它说了两件事:

  
      
  1. 错误:此函数需要1个参数,但提供了0个参数
  2.   
  3. 错误:明确使用未装箱的闭包方法call是实验性的[E0174]
  4.   

我不确定第一个错误,但我认为如果它是实验性的话我现在不会使用此功能。

有没有办法在方法中调用闭包?

2 个答案:

答案 0 :(得分:4)

将成员名称括在括号中:

fn do_something(&self) {
    (self.f)()
}

如果我没记错的话,根本原因与解析代码时的优先级有关。 self.f()会查找标题为f的方法,但由于它不存在会失败。 (self.f)()导致它被不同地解析,特别是寻找成员变量。

答案 1 :(得分:2)

第二个错误是这里的问题,未装箱的闭包很难处理。你需要 可以将闭包(放在指针后面),因为闭包可以有各种奇怪的大小。

编辑:正如Shepmaster指出的那样,这部分不正确。我将扩展下面的旧答案,因为它可能有助于处理闭包并传递它们。

(此外,call是实验性的,在这种情况下不是必需的,所以如果没有这样做,我们就这样做了)

struct A<F> {
    f: Box<F>,
}

现在它已存储在Box(堆分配的内存中,但您可以在必要时使用其他类型的间接),您还应该正确初始化结构:

fn new(f: F) -> A<F> {
    A {
        f: Box::new(f)
    }
}

最后,你可以打电话给它,对吧?

fn do_something(&self) {
    self.f() // Rust being silly
}

但Rust编译器仍然想在这里调用一个方法而不是我们的闭包字段。所以我们明确地取消引用该框:

fn do_something(&self) {
    (*self.f)() // Explain our intentions to the confused compiler
}

现在,它有效!但我们需要这里的间接吗?我这么认为,但似乎不是(谢谢Shep)!您看,A结构已经是通用的,因此它的大小应该适合任何单F类型。因此,我们不需要间接,并且可以使用旧的定义:

struct A<F> {
    f: F,
}

但现在我们至少得到了一些关于此处发生的事情的提示,do_something可以缩减为

fn do_something(&self) {
    (self.f)() // Explicitly access a struct member, then call it
}

所以看起来它只是Rust编译器关于调用语法的语法限制。