从函数返回闭包

最后,无箱封锁已经降落,所以我正在试验他们看看你能做什么。

我有这个简单的function:

fn make_adder(a: int, b: int) -> || -> int { || a + b } 

但是,我得到一个missing lifetime specifier [E0106]错误。 我试图通过将返回types更改为||: 'static -> int来解决此问题,但是cannot infer an appropriate lifetime due to conflicting requirements ,我得到另一个错误cannot infer an appropriate lifetime due to conflicting requirements

如果我理解正确,封闭是unboxed,所以它拥有ab 。 对我来说,这似乎很奇怪,它需要一生。 我该如何解决这个问题?

至于PR#35091 (现在只能在夜间使用Rust),您可以使用impl trait

 #![feature(conservative_impl_trait)] fn make_adder(a: i32) -> impl Fn(i32) -> i32 { move |b| a + b } fn main() { println!("{}", make_adder(1)(2)); } 

这允许返回一个未装箱的闭包,即使不可能指定闭包的确切types。

如果你在你的函数中有任何条件,这将不会对你有所帮助:

 fn make_adder(a: i32) -> impl Fn(i32) -> i32 { if a > 0 { move |b| a + b } else { move |b| a - b } } 

这里没有一个返回types, 每个封闭都有一个独特的,不可闻的types。 在这种情况下,您需要使用间接。 常见的解决scheme是特质对象 ,如其他答案中所述 。

可以返回Box es中的闭包,也就是作为实现某些特征的特征对象:

 fn make_adder(a: i32) -> Box<Fn(i32) -> i32> { Box::new(move |b| a + b) } fn main() { println!("{}", make_adder(1)(2)); } 

( 在这里试试)

还有一个关于添加无盒抽象返回types的RFC ( 它的跟踪问题 ),它允许按值返回闭包,没有框,但是这个RFC被推迟了。 根据该RFC中的讨论,最近似乎有一些工作已经完成,所以可能相对较快的是取消装箱的抽象返回types。

|| 语法仍然是旧的盒装闭包,所以这不起作用的原因以前没有。

而且,即使使用正确的盒装闭包语法|&:| -> int也不行 |&:| -> int ,因为它是字面上只是某些特质的糖。 目前,糖的语法是|X: args...| -> ret |X: args...| -> ret ,其中X可以是&&mut或者什么也不是,对应于FnFnMutFnOnce特征,你也可以为非加糖forms写Fn<(args...), ret>等。 糖可能会改变(可能像Fn(args...) -> ret )。

每一个unboxed闭包都有一个由编译器在内部生成的唯一的,无名的types:讨论unboxed闭包的唯一方法是通过generics和特征边界。 特别是写作

 fn make_adder(a: int, b: int) -> |&:| -> int { |&:| a + b } 

就像写作一样

 fn make_adder(a: int, b: int) -> Fn<(), int> { |&:| a + b } 

即说make_adder返回一个make_adder特性值; 这在目前没什么意义。 首先要尝试的是

 fn make_adder<F: Fn<(), int>>(a: int, b: int) -> F { |&:| a + b } 

但是这是说make_adder返回调用者select的任何F ,而我们要说它返回一些固定的(但“隐藏”)types。 这需要抽象返回types ,基本上说,“返回值实现这个特性”,同时仍然被拆箱和静态parsing。 在那个(暂时closures的)RFC的语言中,

 fn make_adder(a: int, b: int) -> impl Fn<(), int> { |&:| a + b } 

或者与closures糖。

(另一个小问题是:我对解封封闭并不十分确定,但旧封闭当然仍然是通过引用来捕获的东西,这是另一回事,就是这个问题中提出的代码,这已经在#16610中得到纠正。