【问题标题】:How to use a closure as an argument of another closure?如何使用闭包作为另一个闭包的参数?
【发布时间】:2016-04-14 16:53:44
【问题描述】:

代码如下:

fn main() {
  let arg = | | println!("closure");
  let call_twice = | c | { c(); c(); };
  call_twice(arg);
}

但编译器无法推断出参数c 的正确类型。错误信息:

error: the type of this value must be known in this context

我如何告诉编译器参数的类型是一个泛型类型,它隐含Fn


编辑:如果参数类型是 trait 对象,代码可以被编译器接受。但是间接不是必需的,是吗?

fn main() {
  let arg = | | println!("closure");
  let call_twice = | c :&Fn() | { c(); c(); };
  call_twice(&arg);
}

感谢您的回答。但让我困惑的是类型推断问题。使用fn 可以使编译器满意。

fn main() {
 let arg = | | println!("closure");

 // now compiler knows the argument `c` is a closure
 fn call_twice<F>(c: F) where F:Fn() {c(); c();}

 call_twice(arg);
}

我们可以添加一个语法来支持类似的功能吗?如for&lt;F&gt; | c:F | where F:Fn() {c(); c();}

【问题讨论】:

  • 我们可以添加一个语法来支持类似的功能吗? 这不是 Stack Overflow 的问题,你可以在 reddit (r/rust) 或 Rust 论坛上提问。

标签: closures rust type-inference


【解决方案1】:

按照the guidelines in the Rust book section on returning closures 将闭包变成move 闭包并将其装箱,这是我必须做的才能让您的程序在the Rust Playground 运行:

fn main() {
    let arg = Box::new(move || println!("closure"));
    let call_twice = |c: Box<Fn()>| { c(); c(); };
    call_twice(arg);
}

编辑以解决 OP 的最新编辑:不。您要处理的问题最终不是类型推断问题。如果只是类型推断,那么我们所要做的就是告诉闭包c 是一个闭包。实际问题是“闭包参数必须是局部变量,并且所有局部变量必须具有在编译时已知的大小。”另一方面,Rust 函数参数显然没有这个要求。

【讨论】:

  • 作为一个完整的 Rust 新手,我不得不说你编辑中的一点点间接看起来比我的解决方案干净得多。我怀疑由于 Rust 在编译时需要已知参数大小,因此绝对需要装箱或间接。
  • 这里不需要move
  • 既然这个闭包实际上并没有被返回,那么用借用把它放在栈上,而不是用盒子放在堆上不是更好吗?
  • @MatthieuM,你说得对。你能解释一下为什么move 是不必要的吗? @AlexKnauth,这基本上不是 OP 在他的间接编辑中所做的吗?
  • @JudahMeek: move 仅在 (1) 您捕获变量和 (2) 您不能借用其中一个足够长的时间时才需要。在这里,您没有捕获任何变量,因此没有必要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-11
  • 2015-11-30
相关资源
最近更新 更多