我想写一个int
- 返回函数,它接受一个带零参数的闭包,一个带一个参数的闭包,一个带两个参数的闭包,其中所有闭包参数都是int
类型的每个闭包返回f32
。
该功能的签名是什么样的?
现在我想通过Fn
和FnMut
特征接受。签名是什么样的?是否需要使用箱子中的功能?如果是这样,哪些是为什么?为什么?
如果知道:它看起来像什么糖?脱糖?
如果知道:未来可能会发生什么变化?
答案 0 :(得分:10)
我想编写一个接受闭包的int返回函数 取零参数,闭包一个参数,一个闭包 取两个参数,其中所有闭包参数都是int和 每个闭包返回f32。
该功能的签名是什么样的?
目前功能签名及其使用情况(2014-10-26每晚)可能如下所示:
#![feature(unboxed_closures, unboxed_closure_sugar, overloaded_calls)]
fn closures<F1, F2, F3>(mut f1: F1, mut f2: F2, mut f3: F3) -> int
where F1: FnMut() -> f32,
F2: FnMut(int) -> f32,
F3: FnMut(int, int) -> f32 {
(f1() + f2(10) + f3(20, 30)) as int
}
fn main() {
let x = closures(
|&mut:| 0.1,
|&mut: x: int| (2*x) as f32,
|&mut: x: int, y: int| (x + y) as f32
);
println!("{}", x);
}
您可以使用Fn
代替FnMut
(并在mut
,f1
和f2
之前移除f3
)调用者传递的闭包不会改变他们的环境,但总的来说,我想,你会想要使用FnMut
。
此代码使用未装箱的封闭糖和重载调用。没有它们,它看起来像这样:
#![feature(unboxed_closures)]
fn closures<F1, F2, F3>(mut f1: F1, mut f2: F2, mut f3: F3) -> int
where F1: FnMut<(), f32>,
F2: FnMut<(int,), f32>,
F3: FnMut<(int, int), f32> {
(f1.call_mut(()) + f2.call_mut((10,)) + f3.call_mut((20, 30))) as int
}
fn main() {
let x = closures(
|&mut:| 0.1,
|&mut: x: int| (2*x) as f32,
|&mut: x: int, y: int| (x + y) as f32
);
println!("{}", x);
}
糖用于美化闭包类型语法,重载调用功能允许省略显式call_*
方法。
至于将来会发生什么变化,那么闭包构造语法很可能会被简化(当前的闭包被删除时),所以main()
位看起来像这样:
fn main() {
let x = closures(
|| 0.1,
|x| (2*x) as f32,
|x, y| (x + y) as f32
);
println!("{}", x);
}
将推断出闭包的实际类型(FnMut
,Fn
或FnOnce
)。
还会有其他更改,例如从函数返回的闭包的move
关键字(move
会影响变量捕获语义)。这由this接受的RFC包含。
通常,this RFC中列出了未装箱的闭包。但是,它没有更新,因为新的闭包糖语法和其他微妙的变化;最好关注Rust issue tracker以了解更多信息。例如,在this bug中聚合了许多未装箱的闭包问题。
答案 1 :(得分:4)
Fn
,FnMut
和FnOnce
是未装箱的闭包引入的三种特质类型。除了单个方法的名称之外,这些特征之间的区别在于这些方法的self
参数的传递方式不同:
Fn
:&self
(通过引用,不能改变闭包的环境)FnMut
:&mut self
(通过引用,可以改变闭包的环境)FnOnce
:self
(按值,使用闭包,因此闭包只能调用一次)这些特征有两个类型参数:Args
,它是表示闭包参数的元组类型(如果闭包没有参数则为()
)和Result
,这是关闭的返回类型。
现在回答你的问题:
关闭零参数:
fn foo<F: Fn<(), f32>>(closure: F) -> int {
0
}
或者,可以使用where
子句写入绑定:
fn foo<F>(closure: F) -> int where F: Fn<(), f32> {
0
}
关闭一个论点:
fn foo<F: Fn<(int), f32>>(closure: F) -> int {
0
}
关闭有两个论点:
fn foo<F: Fn<(int, int), f32>>(closure: F) -> int {
0
}
关闭采取零参数,加糖形式:
fn foo<F: Fn() -> f32>(closure: F) -> int {
0
}
关闭采取一个论点,加糖形式:
fn foo<F: Fn(int) -> f32>(closure: F) -> int {
0
}
关闭采取两个论点,加糖形式:
fn foo<F: Fn(int, int) -> f32>(closure: F) -> int {
0
}
旧的“盒装”封口正在消失。您可以在metabug上跟踪未装箱的闭包上的错误。