【Rust自学】13.2. 闭包 Pt.2:闭包的类型推断和标注

13.2.0. 写在正文之前

Rust语言在设计过程中收到了很多语言的启发,而函数式编程对Rust产生了非常显著的影响。函数式编程通常包括通过将函数作为值传递给参数、从其他函数返回它们、将它们分配给变量以供以后执行等等。

在本章中,我们会讨论 Rust 的一些特性,这些特性与许多语言中通常称为函数式的特性相似:

  • 闭包(本文)
  • 迭代器
  • 使用闭包和迭代器改进I/O项目
  • 闭包和迭代器的性能

喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)
请添加图片描述

13.2.1. 闭包的类型推断

fn定义的函数不同,闭包不强制要求标注参数和返回值的类型。

函数需要强制标注是因为它是暴露给用户的显示接口的一部分,严格定义接口有助于所有人对参数和返回值的类型取得共识。

闭包并不会被用于这样的暴露接口,只会被存于变量中,使用时也不需要命名,更不会被暴露给我们代码库的用户。所以,闭包不强制要求标注参数和返回值的类型。

而且闭包通常很短小,只在狭小的上下文中工作,编译器通常能推断出类型。当然你手动标注出来也不是不可以。

看个例子:
这是使用函数定义的代码:

fn simulated_expensive_calculation(intensity: u32) -> u32 {  println!("calculating slowly...");  thread::sleep(Duration::from_secs(2));  intensity  
}

这是使用闭包的代码:

let expensive_closure = |num:u32| -> u32 {  println!("calculating slowly...");  thread::sleep(Duration::from_secs(2));  num  
};

这里使用显式标注是因为没有前后文供Rust推断类型,如果有,就不需要:

fn generate_workout(intensity: u32, random_number: u32) {  let expensive_closure = |num| {  println!("calculating slowly...");  thread::sleep(Duration::from_secs(2));  num  };  if intensity < 25 {  println!("Today, do {} pushups!", expensive_closure(intensity));  println!("Next, do {} situps!", expensive_closure(intensity));  } else {  if random_number == 3 {  println!("Take a break today! Remember to stay hydrated!");  } else {  println!("Today, run for {} minutes!", expensive_closure(intensity));  }  }  
}

这里的参数num不需要显式声明类型是因为下文的调用中传进去的参数intensity的类型为u32,Rust推断出num的类型为u32

13.2.2. 函数和闭包定义的语法

这里有4个例子:

 fn  add_one_v1   (x: u32) -> u32 { x + 1 }
let add_one_v2 = |x: u32| -> u32 { x + 1 };
let add_one_v3 = |x|             { x + 1 };
let add_one_v4 = |x|               x + 1  ;
  • 第一个是函数的定义,有函数名,形参名及类型和返回值类型
  • 第二个是闭包的定义,有参数和返回值的类型。这个闭包看着和函数的定义差不多。
  • 第三个同样是闭包,但是没有标注参数和返回值的类型,就得靠编译器推断了。
  • 第四个闭包跟第三个的不同之处在于没有了花括号{}。因为只有一个表达式,所以闭包的{}也可以被省略

13.2.3. 闭包的类型推断

闭包的定义最终只会为参数/返回值推断出唯一具体的类型。

看个例子:

    let example_closure = |x| x;let s = example_closure(String::from("hello"));let n = example_closure(5);

输出:

$ cargo runCompiling closure-example v0.1.0 (file:///projects/closure-example)
error[E0308]: mismatched types--> src/main.rs:5:29|
5 |     let n = example_closure(5);|             --------------- ^- help: try using a conversion method: `.to_string()`|             |               ||             |               expected `String`, found integer|             arguments to this function are incorrect|
note: expected because the closure was earlier called with an argument of type `String`--> src/main.rs:4:29|
4 |     let s = example_closure(String::from("hello"));|             --------------- ^^^^^^^^^^^^^^^^^^^^^ expected because this argument is of type `String`|             ||             in this closure call
note: closure parameter defined here--> src/main.rs:2:28|
2 |     let example_closure = |x| x;|                            ^For more information about this error, try `rustc --explain E0308`.
error: could not compile `closure-example` (bin "closure-example") due to 1 previous error

Rust编译器在闭包第一次被调用时发现它接收的值和输出的值都是String类型,就锁定这个闭包的参数和返回值都是String类型。所以后面又使用i32类型时就会报错。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/66193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JavaScript】比较运算符的运用、定义函数、if(){}...esle{} 语句

比较运算符 !><> < 自定义函数&#xff1a; function 函数名&#xff08;&#xff09;{ } 判断语句&#xff1a; if(判断){ }else if(判断){ 。。。。。。 }else{ } 代码示例&#xff1a; <!DOCTYPE html> <html> <head><meta charset&quo…

WOA-Transformer鲸鱼算法优化编码器时间序列预测(Matlab实现)

WOA-Transformer鲸鱼算法优化编码器时间序列预测&#xff08;Matlab实现&#xff09; 目录 WOA-Transformer鲸鱼算法优化编码器时间序列预测&#xff08;Matlab实现&#xff09;预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现WOA-Transformer鲸鱼算法优化编…

25/1/15 嵌入式笔记 初学STM32F108

GPIO初始化函数 GPIO_Ini&#xff1a;初始化GPIO引脚的模式&#xff0c;速度和引脚号 GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化GPIOA的引脚0 GPIO输出控制函数 GPIO_SetBits&#xff1a;将指定的GPIO引脚设置为高电平 GPIO_SetBits(GPIOA, GPIO_Pin_0); // 将GPIO…

mac m4 安装 node

brew install node // 安装 node //安装的路径在&#xff1a; /opt/homebrew/bin/node brew install node14 // brew install node22 // 安装指定版本 如果需要设置环境变量&#xff1a;通过&#xff1a; which node 查找路径 export PATH"/usr/local/opt/…

haproxy+nginx网站架构,实现负载均衡实验笔记

前提准备&#xff1a; 两台nginx&#xff0c;一台haproxynginx1&#xff1a;192.168.180.120nginx2&#xff1a;192.168.180.130&#xff0c;NFShaproxy&#xff1a;192.168.180.110 nginx&#xff08;两台nginx的操作是一样的&#xff09;&#xff1a; 1. 安装nginx #先安…

【C++篇】红黑树的实现

目录 前言&#xff1a; 一&#xff0c;红黑树的概念 1.1&#xff0c;红黑树的规则 1.2&#xff0c;红黑树的最长路径 1.3&#xff0c;红黑树的效率分析 二&#xff0c;红黑树的实现 2.1&#xff0c;红黑树的结构 2.2&#xff0c;红黑树的插入 2.2.1&#xff0c;大致过程…

如何在谷歌浏览器中设置自定义安全警告

随着网络环境的日益复杂&#xff0c;浏览器的安全问题也愈发引人关注。谷歌浏览器作为一款广泛使用的浏览器&#xff0c;其自定义安全警告功能为用户提供了更加个性化和安全的浏览体验。本文将详细介绍如何在谷歌浏览器中设置自定义安全警告&#xff0c;帮助用户更好地保护自己…

Spring 6 第1章——概述

一.Spring是什么 Spring是一款主流的Java EE轻量级&#xff08;体积小、不需要依赖其它组件&#xff09;开源框架Spring的目的是用于简化Java企业级应用的开发难度和开发周期Spring的用途不仅限于服务端的开发&#xff0c;从简单性、可测试性和松耦合的角度而言&#xff0c;任…

C语言预处理艺术:编译前的魔法之旅

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文一、预处理的作用与流程&#xf…

基于Springboot + vue实现的旅游网站

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

docker-compose和docker仓库

一、docker-compose 1.概述 docker-compose是一个自动编排工具&#xff0c;可以根据dockerfile自动化部署docker容器。 主要功能 配置定义 使用YAML文件&#xff08;通常命名为docker - compose.yml&#xff09;来描述应用程序的服务、网络和卷等配置。 容器编排 可以同时…

MAC AndroidStudio模拟器无网络

先确认PC端是正常访问网络的&#xff1b; 模拟器端修改Wifi设置&#xff1a;设置 - 网络和互联网 - WALN设置 按照上图修改&#xff1b; IP设置&#xff1a;从DHCP修改为静态&#xff0c;IP地址&#xff1a;10.0.2.16 &#xff0c;网关&#xff1a;10.0.2.2 &#xff0c; DNS…

nvim 打造成可用的IDE(2)

上一个 文章写的太长了&#xff0c; 后来再写东西 就一卡一卡的&#xff0c;所以新开一个。 主要是关于 bufferline的。 之前我的界面是这样的。 这个图标很不舒服有。 后来发现是在这里进行配置。 我也不知道&#xff0c;这个配置 我是从哪 抄过来的。 测试结果&#xff1…

升级 SpringBoot3 全项目讲解 — 为什么 SpringBoot3 应该抛弃 Maven,搭配 Gradle 来使用?

学会这款 &#x1f525;全新设计的 Java 脚手架 &#xff0c;从此面试不再怕&#xff01; 随着 Spring Boot 3 的发布&#xff0c;许多开发者开始考虑如何将现有项目升级到最新版本。Spring Boot 3 带来了许多新特性&#xff0c;包括对 Java 17 的支持、更好的性能优化以及对 G…

如何优化Elasticsearch大文档查询?

记录一次业务复杂场景下DSL优化的过程 背景 B端商城业务有一个场景就是客户可见的产品列表是需要N多闸口及各种其它逻辑组合过滤的&#xff0c;各种闸口数据及产品数据都是存储在ES的(有的是独立索引&#xff0c;有的是作为产品属性存储在产品文档上)。 在实际使用的过程中&a…

openCvSharp 计算机视觉图片找茬

一、安装包 <PackageReference Include"OpenCvSharp4" Version"4.10.0.20241108" /> <PackageReference Include"OpenCvSharp4.runtime.win" Version"4.10.0.20241108" /> 二、准备两张图片 三、编写代码 using OpenCv…

实战:FRP内网穿透部署-支持ssh、web访问

目录 1 准备工作2 公网服务器部署server端2.1 frps.ini配置 3 内网客户端部署client端3.1 frpc.ini配置&#xff08;内网服务器01&#xff09;3.2 frpc.ini配置&#xff08;内网服务器02&#xff09; 4 服务启动脚本4.1 公网服务器 server4.2 内网服务器 client 2 systemctl常见…

Uniapp中实现加载更多、下拉刷新、返回顶部功能

一、加载更多&#xff1a; 在到达底部时&#xff0c;将新请求过来的数据追加到原来的数组即可&#xff1a; import {onReachBottom } from "dcloudio/uni-app";const pets ref([]); // 显示数据function network() {uni.request({url: "https://api.thecatap…

Flutter:封装ActionSheet 操作菜单

演示效果图 action_sheet_util.dart import package:ducafe_ui_core/ducafe_ui_core.dart; import package:flutter/material.dart; import package:demo/common/index.dart;class ActionSheetUtil {/// 底部操作表/// [context] 上下文/// [title] 标题/// [items] 选项列表 …

【Rust练习】28.use and pub

练习题来自&#xff1a;https://practice-zh.course.rs/crate-module/use-pub.html 1 使用 use 可以将两个同名类型引入到当前作用域中&#xff0c;但是别忘了 as 关键字. use std::fmt::Result; use std::io::Result;fn main() {}利用as可以将重名的内容取别名&#xff1a;…