我尝试从结构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个参数,但提供了0个参数
- 错误:明确使用未装箱的闭包方法
醇>call
是实验性的[E0174]
我不确定第一个错误,但我认为如果它是实验性的话我现在不会使用此功能。
有没有办法在方法中调用闭包?
答案 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编译器关于调用语法的语法限制。