Rust Turbofish 的由来

0x01 什么是 Turbofish
我们运行如下 Rust Snippet:
fn main() {let numbers: Vec<i32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];let even_numbers = numbers.into_iter().filter(|n| n % 2 == 0).collect();println!("{:?}", even_numbers);
}
不出意外,Rust 编译器一定会抛出错误
aggresss@traitx tmp % branch:[main]% cargo checkChecking tmp v0.1.0 (/tmp)
error[E0283]: type annotations needed--> tmp/src/main.rs:3:9|
3 | let even_numbers = numbers.into_iter().filter(|n| n % 2 == 0).collect();| ^^^^^^^^^^^^ ------- type must be known at this point|= note: cannot satisfy `_: FromIterator<i32>`
note: required by a bound in `collect`--> /Users/aggresss/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2050:19|
2050 | fn collect<B: FromIterator<Self::Item>>(self) -> B| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
help: consider giving `even_numbers` an explicit type|
3 | let even_numbers: Vec<_> = numbers.into_iter().filter(|n| n % 2 == 0).collect();| ++++++++For more information about this error, try `rustc --explain E0283`.
error: could not compile `tmp` (bin "tmp") due to 1 previous error
上面的错误可以通过两种方式解决
-
第一种方式在 even_numbers 变量声明时声明类型:
let even_numbers: Vec<_> = numbers.into_iter().filter(|n| n % 2 == 0).collect(); -
第二种方式使用 Turbofish 语法,在泛型函数后面加入
::<>:let even_numbers = numbers.into_iter().filter(|n| n % 2 == 0).collect::<Vec<_>>();
泛型在编译的过程中要被实例化,大多数情况下,具体类型是基于 Hindley-Milner 理论的类型推断,但是在一些特殊情况下,我们需要显示声明类型来帮助编译器排除歧义,这也是 Turbofish 存在的原因。
在使用泛型的过程中,其他语言也会遇到类似的问题,例如 C++ 中使用 ident<T>,或者 Golang 中使用 ident[T],而 Rust 中确使用 ident::<T>,多了两个冒号(double colon),第一次看到确实觉得有点多余,通过考古在 reddit 上看到 Anna Harren (u/deadstone) 的解释后理解了这样设计的初衷,即可以降低编译器的语法解析难度。

这是一种从语言设计者角度的 Tradeoff,所以语言的使用者多少会有一些疑问或抱怨,在 Rust 社区中确实也会时常听到一些相关的声音,但是当知道了 Turbofish 语法由来的故事后,我已经开始喜欢 ::<> 这个符号。
0x02 Turbofish 的由来
在 2015 年的时候,Anna Harren 第一次提出使用 ::<> 来辅助编译器进行类型判断,同时给它起了一个很有意思的名字 –– TURBOFISH,很快这个名字也被 Rust 官方所采纳,这个符号确实挺像一条加速的鱼,还有人做了一个页面 https://turbo.fish/。不幸的是在 2021 年 Anna Harren 因患癌症离开了这个世界,Rust 1.55.0 的 Release Note 特别提到了她,并将这个版本作为对 Anna Harren 的纪念。

可能开源社区的魅力就在于对多样性的包容,Rust 社区争吵不断,但更容易诞生有趣的事物,毕竟这个世界有那么多有趣的灵魂。
0x03 Furthermore
有一个彩蛋发现,将 Turbofish 符号 ::<> 倒过来, 即 <>::,Rust 在 Disambiguating Function Calls 中使用 :: 作为 namespace qualifier,同时使用 <>:: 作为路径中存在类型混淆时的显示声明,例如:
fn main() {let s = "Hello, World!";let string = <&str as Into<String>>::into(&s);println!("{}", string);
}
这种方法早期被叫做 UFCS (Universal Function Call Syntax),于此同时,使用 Turbofish 也可以反向解决上面的问题:
fn main() {let s = "Hello, World!";let string = Into::<String>::into(s);println!("{}", string);
}
从优雅对称的角度看,我还是支持 Turbofish 仍然是 Turbofish。
0x04 Reference
- https://www.reddit.com/r/rust/comments/3fimgp/comment/ctozkd0/
- https://github.com/rust-lang/rust/blob/master/tests/ui/parser/bastion-of-the-turbofish.rs
- https://foundation.rust-lang.org/news/member-spotlight-turbofish/
- https://turbo.fish/
- https://github.com/jplatte/turbo.fish
- https://blog.rust-lang.org/2021/09/09/Rust-1.55.0.html#dedication
- https://matematikaadit.github.io/posts/rust-turbofish.html
- https://www.reddit.com/r/rust/comments/v4rir6/turbofish_why/
- https://techblog.tonsser.com/posts/what-is-rusts-turbofish
- https://doc.rust-lang.org/reference/expressions/call-expr.html
相关文章:
Rust Turbofish 的由来
0x01 什么是 Turbofish 我们运行如下 Rust Snippet: fn main() {let numbers: Vec<i32> vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];let even_numbers numbers.into_iter().filter(|n| n % 2 0).collect();println!("{:?}", even_numbers); }不出意…...
2.外卖点餐系统(Java项目 springboot)
目录 0.系统的受众说明 1.系统功能设计 2.系统结构设计 3.数据库设计 3.1实体ER图 3.2数据表 4.系统实现 4.1用户功能模块 4.2管理员功能模块 4.3商家功能模块 4.4用户前台功能模块 4.5骑手功能模块 5.相关说明 新鲜运行起来的项目:如需要源码数据库…...
Universal Thresholdizer:将多种密码学原语门限化
参考文献: [LS90] Lapidot D, Shamir A. Publicly verifiable non-interactive zero-knowledge proofs[C]//Advances in Cryptology-CRYPTO’90: Proceedings 10. Springer Berlin Heidelberg, 1991: 353-365.[Shoup00] Shoup V. Practical threshold signatures[C…...
【UE5学习笔记】编辑及运行界面:关闭眼部识别(自动曝光)
自动曝光,也就是走进一个黑暗的环境,画面会逐渐变量,以模拟人眼进入黑暗空间时瞳孔放大,进光量增加的一种真实视觉感受: 制作过程中是否关闭自动曝光,取决于游戏的性质,但是个人认为,…...
未来科技的前沿:深入探讨人工智能的进展、机器学习技术和未来趋势
文章目录 一、人工智能的定义和概述1. 人工智能的基本概念2. 人工智能的发展历史 二、技术深入:机器学习、深度学习和神经网络1. 机器学习2. 深度学习3. 神经网络 三、人工智能的主要目标和功能1. 自动化和效率提升2. 决策支持和风险管理3. 个性化服务和预测未来 本…...
3-qt综合实例-贪吃蛇的游戏程序
引言: 如题,本次实践课程主要讲解贪吃蛇游戏程序。 qt贪吃蛇项目内容: 一、功能需求 二、界面设计 各组件使用: 对象名 类 说明 Widget QWidge 主窗体 btnRank QPushButton 排行榜-按钮 groupBox QGroupBox 难…...
QGraphicsView实现简易地图12『平移与偏移』
前文链接:QGraphicsView实现简易地图11『指定层级-定位坐标』 提供地图平移与偏移功能。地图平移是指将地图的中心点更改为给定的点,即移动地图到指定位置。地图偏移是指将当前视口内的地图向上/下/左/右/进行微调,这里偏移视口宽/高的四分之…...
深入探索 Vue 中的 createVNode 与 resolveComponent
在 Vue 开发中,createVNode和resolveComponent是两个至关重要的工具,它们为我们提供了强大的能力来灵活地创建和操控组件。 一、首先,让我们深入了解一下createVNode。 这是一个用于创建虚拟节点的关键函数,通过它,我…...
【记录42】centos 7.6安装nginx教程详细教程
环境:腾讯云centos7.6 需求:安装nginx-1.24.0 1. 切入home文件 cd home 2. 创建nginx文件 mkdir nginx 3. 切入nginx文件 cd nginx 4. 下载nginx安装包 wget https://nginx.org/download/nginx-1.24.0.tar.gz 5. 解压安装包 tar -zxvf nginx-1.24.0.…...
C语言程序设计(不熟悉的点)
一、switch多路分支语句 二、条件表达式 三、循环 for循环: for循环的三个表达式不是必须的,第一个表达式之前声明过,可以不写,第三个表达式可以放在循环体里面;第二个表达式可以不写,为死循环。 空循环…...
DAO是什么?有什么用途?
DAO(Decentralized Autonomous Organization,去中心化自治组织)是一种基于区块链技术的组织形式,它没有中央管理层,而是通过智能合约和区块链上的代码来运作。DAO 的决策过程是透明的,通常由组织的成员通过…...
Socket学习记录
本次学习Socket的编程开发,该技术在一些通讯软件,比如说微信,QQ等有广泛应用。 网络结构 这些都是计算机网络中的内容,我们在这里简单回顾一下: UDP(User Datagram Protocol):用户数据报协议;TCP(Transmission Contr…...
黑马 - websocket搭建在线聊天室
这里写自定义目录标题 一、消息推送常见方式二、websocket 是什么?三、websocket api的介绍1、客户端 (浏览器)2、服务端api 四、实现在线聊天室1、需求2、聊天室流程分析3、消息格式4、代码实现 一、消息推送常见方式 1、轮训方式 2、SSE…...
【每日力扣】543. 二叉树的直径与101. 对称二叉树
🔥 个人主页: 黑洞晓威 😀你不必等到非常厉害,才敢开始,你需要开始,才会变的非常厉害 543. 二叉树的直径 给你一棵二叉树的根节点,返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的…...
【linux】——日志分析
1. 日志文件 1.1 日志文件的分类 日志文件: 是用于记录Linux系统中各种运行消息的文件,相当于Linux主机的“日记". 日志文件对于诊断和解决系统中的问题很有帮助,系统一旦出现问题时及时分析日志就会“有据可查”。此外。当主机遭受攻…...
【intro】GraphSAGE
论文 https://arxiv.org/pdf/1706.02216 abstract 大图中节点的低维embedding已经被证明在各种预测任务中非常有用,然而,大多数现有的方法要求在embedding训练期间图中的所有节点都存在;这些先前的方法属于直推式(transductive)…...
管理能力学习笔记九:授权的常见误区和如何有效授权
授权的常见误区 误区一:随意授权 管理者在授权工作时,需要依据下属的能力、经验、意愿问最自己:这项工作适合授权给Ta做吗?如果没有,可以通过哪些方法进行培训呢? 误区二:缺乏信任 心理暗示…...
第21天 反射
反射概述 想象一下,你在一个房间里边,但你看不见自己,也不知道自己是谁。这时候你面前有一个镜子,你可以通过镜子的反射来观察自己。反射就像这面镜子。它让你能够检查、分析、修改Java中的对象、类、方法等 使用情况࿱…...
多链路聚合设备是什么
多链路聚合设备属于通信指挥装备。 乾元通多链路聚合设备,它能够将多个网络链路聚合成一个逻辑链路,以实现高速、稳定、可靠的数据传输。多链路聚合设备的核心技术包括链路聚合、负载均衡、故障切换等,能够智能管理和优化利用不同网络链路&a…...
基于springboot+vue+Mysql的自习室预订系统
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
C++实现分布式网络通信框架RPC(2)——rpc发布端
有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...
智能职业发展系统:AI驱动的职业规划平台技术解析
智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...
