如何在 Rust 函数签名中使用 Fn 特征(闭包)? [英] How to use the Fn traits (closures) in Rust function signatures?

查看:33
本文介绍了如何在 Rust 函数签名中使用 Fn 特征(闭包)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to write an i32-returning function that accepts a closure taking zero arguments, a closure taking one argument, and a closure taking two arguments, where all closure arguments are of type i32 and every closure returns f32.

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

What is that function's signature going to look like?

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

I want to accept these via the Fn and FnMut traits. What does the signature look like? Is the use of features in the crate required? If so, which ones and why?

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

If known: what does it look like sugared? Desugared?

如果知道:未来可能会发生什么变化?

If known: what is likely to be changed in the future?

推荐答案

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

I want to write an i32-returning function that accepts a closure taking zero arguments, a closure taking one argument, and a closure taking two arguments, where all closure arguments are of type i32 and every closure returns f32.

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

What is that function's signature going to look like?

看起来像这样:

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(并在 f1f2<之前删除 mut/code> 和 f3) 如果你想强制调用者传递不会改变他们环境的闭包,但总的来说,我认为,你会想要使用 FnMut.

You can use Fn instead of FnMut (and remove mut before f1, f2 and f3) if you want to force the caller to pass closures which don't mutate their environment, but in general, I think, you would want to use FnMut.

此代码使用未装箱的闭包糖和重载调用.没有它们,它看起来像这样:

This code uses unboxed closure sugar and overloaded calls. Without them, it would look like this:

#![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);
}

糖用于美化闭包类型的语法,重载调用功能允许省略显式的call_*方法.

The sugar is used to prettify closure type syntax, and the overloaded calls feature allows to omit explicit call_* methods.

编者注这个问题是在 Rust 1.0 之前提出的,本节仅适用于那时和 1.0 之间发生的变化.

Editor's note This question was asked before Rust 1.0, and this section only applies to the changes that happened between then and 1.0.

至于未来会发生什么变化,那么闭包的构造语法很可能会被简化(当当前的闭包被删除时),所以 main() 位将从这里改变:

As for what's going to change in future, then it is likely that closure construction syntax would be simplified (when current closures are dropped), so the main() bit will change from this:

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).

The actual type of the closure (FnMut, Fn or FnOnce) is going to be inferred.

还会有其他更改,例如用于从函数返回的闭包的 move 关键字(move 影响变量捕获语义).这由this 接受 RFC.

There will also be other changes, like the move keyword for closures which are returned from functions (move affects variable capturing semantics). This is covered by this accepted RFC.

通常,未装箱的闭包在this RFC.然而,它没有使用新的闭包糖语法和其他细微的变化进行更新;最好关注 Rust issue tracker 以了解更多信息.例如,许多未装箱闭包的问题都聚集在 this 错误中.

In general, unboxed closures are outlined in this RFC. It is not updated, however, with new closures sugar syntax and with other subtle changes; it may be better to follow Rust issue tracker to find out more on this. For example, a lot of issues with unboxed closures are aggregated in this bug.

这篇关于如何在 Rust 函数签名中使用 Fn 特征(闭包)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆