我想写一个i32返回函数,它接受一个包含零个参数的闭包、一个包含一个参数的闭包和一个包含两个参数的闭包,其中所有闭包参数都是i32类型,每个闭包返回f32.

那个函数的签名会是什么样子?

我想通过FnFnMut个特征来接受这些.签名是什么样子的?是否需要使用 crate 中的功能?如果是的话,是哪些,为什么?

如果知道:它看起来像什么糖?脱糖衣?

如果已知:future 可能会发生什么变化?

推荐答案

我想写一个接受闭包的i32返回函数

那个函数的签名会是什么样子?

看起来是这样的:

fn closures<F1, F2, F3>(mut f1: F1, mut f2: F2, mut f3: F3) -> i32
where
    F1: FnMut() -> f32,
    F2: FnMut(i32) -> f32,
    F3: FnMut(i32, i32) -> f32,
{
    (f1() + f2(10) + f3(20, 30)) as i32
}

fn main() {
    let x = closures(|| 0.1, |x| (2 * x) as f32, |x, y| (x + y) as f32);
    println!("{}", x);
}

如果您想强制调用方传递不会改变其环境的闭包,可以使用Fn而不是FnMut(在f1f2f3之前删除mut),但我认为,一般来说,您会希望使用FnMut.

这段代码使用未装箱的闭包和重载调用.如果没有它们,情况会是这样:

#![feature(unboxed_closures, fn_traits)]

fn closures<F1, F2, F3>(mut f1: F1, mut f2: F2, mut f3: F3) -> i32
where
    F1: FnMut<(), Output = f32>,
    F2: FnMut<(i32,), Output = f32>,
    F3: FnMut<(i32, i32), Output = f32>,
{
    (f1.call_mut(()) + f2.call_mut((10,)) + f3.call_mut((20, 30))) as i32
}

fn main() {
    let x = closures(|| 0.1, |x| (2 * x) as f32, |x, y| (x + y) as f32);
    println!("{}", x);
}

sugar用于修饰闭包类型语法,重载调用特性允许省略显式的call_*个方法.

rust 1.0之前

Editor's note这个问题是在Rust 1.0之前提出的,本节仅适用于在Rust 1.0之前发生的更改.

至于将来会发生什么变化,那么闭包构造语法很可能会被简化(当当前闭包被删除时),因此main()位将发生变化:

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 main() {
    let x = closures(
        || 0.1,
        |x| (2*x) as f32,
        |x, y| (x + y) as f32
    );
    println!("{}", x);
}

将推断闭合的实际类型(FnMutFnFnOnce).

还有其他变化,比如函数返回的闭包的move关键字(move影响变量捕获语义).这包含在this份接受的RFC中.

一般来说,this RFC中概述了未装箱的闭包.然而,它没有更新新的语法和其他微妙的变化;最好是遵循Rust issue tracker了解更多信息.例如,许多与未绑定闭包有关的问题都聚集在一起.

Rust相关问答推荐

泛型属性比较

如何容器化Linux上基于Rust的Windows应用程序的编译过程?

如何正确重新排列代码以绕过铁 rust 借入判断器?

如何修复&q;无法返回引用函数参数的值在异步规则中返回引用当前函数&q;拥有的数据的值?

用于实现获取 struct 体 id 的特征规范

这个不安全的 Rust 代码有什么问题,所以它可以在 Windows 上运行,但不能在 Ubuntu 上运行?

Rust与_有何区别?

实现AsyncWrite到hyper Sender时发生生命周期错误

str 和 String 的 Rust 生命周期

强制特征仅在 Rust 中的给定类型大小上实现

Rust 中的let是做什么的?

类型组的通用枚举

覆盖类型的要求到底是什么?为什么单个元素元组满足它?

如何构建包含本地依赖项的 docker 镜像?

C++ 中的 CRTP 是一种表达其他语言中特征和/或 ADT 的方法吗?

为什么这个 Trait 无效?以及改用什么签名?

基于名称是否存在的条件编译

有什么办法可以用 Rust 访问 Windows 最近的文件夹吗?

来自外部函数的future 内部可变引用

如何在 Rust 中使用特征标志来捕获多行代码?