首页 > 其他分享 >深入Rust函数之函数参数与普遍函数

深入Rust函数之函数参数与普遍函数

时间:2023-03-25 23:46:11浏览次数:60  
标签:函数 迭代 max reduce 函数参数 f32 let Rust

这两天翻阅标准库的时候, 有一个用法让我十分不解:

assert_eq!(
    [2.4, f32::NAN, 1.3]
        .into_iter()
        .reduce(f32::max)
        .unwrap(),
    2.4
);

这个是迭代器中的max中的内容, 在这里, 标准库写道: 因为浮点数并没有实现Ord Trait, 因此对于一个由浮点数组成的集合转化而来的迭代器, 我们没有办法直接调用max方法获取迭代器中元素的最大值, 因为这个方法依赖于Ord Trait, 因此, 想要获得一个浮点数集合中浮点数的最大值, 就有了如上的处理方式.

函数与闭包

然而, 奇怪就奇怪在这里, reduce这个迭代器方法最常见的用法应该是接受一个有两个参数的闭包, 第一个是需要累计的值, 第二个值则是迭代器中的元素, 并且这个闭包需要返回一个值, 实现归约的效果. 最后, reduce迭代器会返回一个一个Option. 当迭代器为空时, reduce会返回一个Option::None

let reduced: i32 = (1..10).reduce(|acc, e| acc + e).unwrap();
assert_eq!(reduced, 45);

// Which is equivalent to doing it with `fold`:
let folded: i32 = (1..10).fold(0, |acc, e| acc + e);
assert_eq!(reduced, folded);

常见的reduce的使用方法就如上面这段标准库中的代码一样. 上面的reducefold都实现了计算0-9, 包括9的和. 差别只是fold可以指定初始值, 而且最后会直接返回结果, 并不会返回Option. 那么问题来了, 像第一段代码中那样, 只是传入了一个不明不白的f32::max又是怎么回事呢?

self签名转化为普遍形式

其实, 阅读函数签名, reduce能够接受的并不只是闭包, 它的范围实际上是F: FnMut(Self::item, Self::item -> Self::item. 这意味着, 所有的接受两个与迭代器中元素的类型相同, 并且返回一个这个类型的值的函数而不仅仅是闭包都可以作为它的参数. f32::max就是这样的一个函数, 然而, 问题到这里并没有完全解决, 若是翻到f32::max的文档, 我们可以发现这个方法实际上接受的是一个self参数和另一个用于比较的f32数值, 它的调用方式实际上应该是这样:

let a: f32 = 1.0;
let b: f32 = 2.0;
assert_eq!(a.max(b), b);

难道reduce不是应该接受一个有两个参数的函数吗? 神奇的事情来了, 在上面这个过程中, 其实有这样一件事情发生了a.max(b) 转化为了f32::max(a, b) , 也就是说, 实际上我们也可以直接以后者的方式调用max这个函数, 这么看来, 把后者放入到reduce对参数的要求中, 就能完美符合答案了.

最后

所以, 回到最开始的那段代码, reduce部分的作用实际上是调用max函数, 将数组中每个浮点数逐一进行比较, 并且保留其中更大的数作为累计值. 之所以要使用f32::max 这个函数, 是因为在数组中还有一个f32:NAN这样的非数字, 而f32::max 可以在比较的时候做到将它忽略, 不影响结果.

最最后

你能通过阅读Rust std中和Reverse以及标准库中实现的最大二叉堆的说明, 结合上面的知识, 解释这段代码的作用和其中Reverse的用法吗?

你可以在Rust Playground运行这顿代码

use std::cmp::Reverse;
use std::collections::BinaryHeap;
fn main() {
    let mut a  = vec![1,2,3];
    let mut b: BinaryHeap<_> = a.iter()
        .map(Reverse)
        .collect();
    while let Some(Reverse(num)) = b.pop(){
        println!("{:?}", num);
    }
}

参考阅读

  1. Stack Overflow Rust最小二叉堆的实现
  2. Rust RFC
  3. Rust论坛

标签:函数,迭代,max,reduce,函数参数,f32,let,Rust
From: https://www.cnblogs.com/echiduna24/p/17255954.html

相关文章

  • C++ sort 函数 以及 priority_queue 的使用
    1.sort函数的使用sort函数的定义:sort(first,end,compare);sort对[first,end)范围内的元素进行排序。默认为升序排序(此时不需要传入compare)。当需要降......
  • Python函数参数类型及可变参数
    参数类型位置参数根据形参位置顺序进行实参传递;关键字参数根据形参名进行实参传递;默认参数给形参设置默认值,实参与默认值不符时需要覆盖传递;可变参数......
  • 函数
    1、库函数   C语言本身所提供的函数,例如:字符串操作函数、字符操作函数、内存操作函数、I/O函数、时间/日期函数、数学函数以及其他库函数2、自定义函数   int(返回......
  • mysql手动实现窗口函数的方法
    背景:窗口函数是一种强大的SQL函数,它允许在查询中对一组行进行计算,而不需要将它们分组或汇总。然而,如果使用的MySQL版本不支持窗口函数,我们仍然可以通过一些技巧手动实现它......
  • Teamcenter_NX集成开发:UF_UGMGR_invoke_pdm_server函数的使用
    之前了解到通过UFUN函数UF_UGMGR_invoke_pdm_server可以调用TeamcenterITK函数,从而可以获取及编辑Teamcenter对象。UFUN中有样例代码,但是就是不知道怎么使用,今天下午看了......
  • sort函数之cmp
        bool static cmp(const  pair<int,int>&a,const pair<int,int>&b)    {        return a.second < b.second ;//从小到大returna.s......
  • 函数练习题2
    ......
  • 函数练习题1
    ......
  • 使用Map+函数式优化if else
    使用Map+函数式接口优化ifelse工作中遇到一个接口要返回不同数据表中的数据,首先想到的是使用if-else或者switchcase:例如: if(("1").equals(dataType)){re......
  • 算法分析与设计——冒泡排序,选择排序,STL自带sort函数性能比较实验
    实验环境:Win11,Devc++5.11实验方法:生成不同数据量的随机数后使用三种排序方法分别排序,比较每种方法所耗时长。实验结果:数据量为1000时,冒泡排序平均用时为0.015s,选择排序平......