2311rust特征
Rust无成本抽象
Rust
中抽象基石是trait
:
1,Trait
是Rust
中唯一的接口
概念.多个类型可实现一个特征
,事实上,可为现有类型提供新的特征
实现.另一方面,想抽象未知类型
时,找特征
就行了.
2,与C++
模板一样,可静态分发特征
.
3,可动态分发特征
.有时确实需要间接
,所以不必运行时"擦除"
抽象.想运行时分发
时,可使用接口
或特征
.
背景:Rust
中的方法
Rust
提供了方法
和自由
函数,它们密切相关:
struct Point {x: f64,y: f64,
}
//把(借用的)点转换为串的`自由`函数
fn point_to_string(point: &Point) -> String { ... }
//"固有的`impl"`块,直接在`类型`上定义了可用的方法
impl Point {//此方法在`Point`上都可用,并自动借用`Point`值fn to_string(&self) -> String { ... }
}
上述to_string
方法叫"固有
"方法,因为它们:
1,(通过impl
)绑定
到单个具体的"self"
类型.
2,在该类型
值上自动
可用.也即,与函数不同,内置
方法总是"在域内".
方法
的第一个参数
总是是显式的"self"
,根据期望的所有权级别
,它是self,&mut self
或&self
.使用.
调用方法.
且self
参数,按方法中使用的self
形式隐式借用
:
let p = Point { x: 1.2, y: -3.7 };
let s1 = point_to_string(&p); //显式借用,调用自由函数.
let s2 = p.to_string(); //按`&p`隐式借用,来调用方法
如下,流式
生成进程的API
:
let child = Command::new("/bin/cat").arg("rusty-ideas.txt").current_dir("/Users/aturon").stdout(Stdio::piped()).spawn();
特征是接口
接口允许每个
代码自由切换
.对特征
,规范主要围绕
方法展开.
如,以下用来哈希
的简单特征:
trait Hash {fn hash(&self) -> u64;
}
为了为给定类型
实现此特征,必须提供匹配签名
的哈希方法:
impl Hash for bool {fn hash(&self) -> u64 {if *self { 0 } else { 1 }}
}
impl Hash for i64 {fn hash(&self) -> u64 {*self as u64}
}
与Java,C#
或Scala
等语言中的接口
不同,可为现有类型
实现新特征(如上面的Hash
).即可在事后创建抽象
,并应用至现有库
.
与内置
方法不同,仅当特征
在域时,特征方法
才在域中.但是假设Hash
在域内,你可编写true.hash()
,因此实现一个特征
扩展了类型
上可用的方法集
.
定义和实现
特征不过是抽象
出多个类型
满足的通用接口
.
静态分发
一般通过泛型
消费特征
:
fn print_hash<T: Hash>(t: &T) {println!("The hash is {}", t.hash())
}
在未知T类型
上,print_hash
函数是泛型
函数,但要求T
实现Hash
特征.即可与bool
和i64
值一起,使用它:
print_hash(&true); //实例化`T=bool`
print_hash(&12_i64); //实例化`T=i64`
静态分发
中编译掉泛型
.也即,与C++
模板一样,编译器生成print_hash
方法的两个副本
来处理上述代码,每个副本
对应一个具体参数类型
.
反之表明内部调用t.hash()
(实际使用抽象点)的成本为零:按直接静态调用相关实现
编译它:
//编译后的代码:直接调用特化`bool`版本
__print_hash_bool(&true); //
__print_hash_i64(&12_i64);
//直接调用特化`i64`版本
对像print_hash
类函数,该编译
模型不是很有用,但对更实际的哈希
使用,却非常有用.假设还引入
了一个相等比较
特征:
trait Eq {fn eq(&self, other: &Self) -> bool;
}
这里按实现trait
的类型解析Self
的引用;在impl Eq for bool
中,它引用bool
.
然后,可定义一个在实现哈希
和Eq
的T类型
上是都通用的哈希映射
:
struct HashMap<Key: Hash + Eq, Value> { ... }
泛型
静态编译模型有几个好处:
1,对具体的Key
和Value
类型,每次使用HashMap
都会产生不同的具体HashMap
类型,即HashMap
可在其存储桶
中内联
(无间接
)布局键和值
.
来可节省空间和间接
,并提高缓存局部性
.
2,HashMap
上的每个方法
同样会生成特化
代码.即,如上,调用哈希
和Eq
,不会产生额外成本
.表明优化器
可用最具体
(也即没有抽象
)的代码.
特别是,静态分发
允许在泛型
用法间内联
.
总之,与在C++
模板一样,你可用泛型
编写无成本的相当高级
的抽象.
但是,与C++
模板不同的是,会提前完全类型检查特征客户
.也即,单独编译HashMap
时,会根据抽象Hash
和Eq
特征检查
一次代码类型
正确性,而不是在每当应用具体类型
时的重复检查
.
即库作者可更早,更清晰
地出现编译错误
,而客户
的类型检查
成本更少(即编译速度
更快).
动态分发
有时,抽象不仅是重用或模块化
,有时在运行时不能去掉抽象
.
如,GUI
框架一般涉及响应事件
(如点击鼠标
)的回调
:
trait ClickCallback {fn on_click(&self, x: i64, y: i64);
}
GUI
元素,常见的是,允许为单个事件
注册多个回调
.对泛型
,可想象这样写:
struct Button<T: ClickCallback> {listeners: Vec<T>,...
}
但问题立即显现
出来:即每个按钮
都按ClickCallback
的一个实现
特化,且按钮类型
反映了该类型
.这不是想要的!
相反,想要一个带一组每个都可能是不同
具体类型,但都实现了ClickCallback
的异构
监听器的Button
类型.
难点是,如果是一组异构类型
,则每个类型
都有不同的大小,则如何才能布局
内部向量?答案
一般是:间接
.在向量
中存储
回调指针:
struct Button {listeners: Vec<Box<ClickCallback>>,...
}
在此,就像它是一个类型
一样,使用ClickCallback
特征.在Rust
中,特征
是类型
,但它们是"无大小的
",只允许出现在Box
(指向堆)或&
(可任意指向)等指针后面
.
在Rust
中,像&ClickCallback
或Box<ClickCallback>
的类型叫"trait对象
",它包括指向实现ClickCallback
的T类型实例
的指针,及一个虚表
:一个指向T对trait
中每个方法
实现的指针
(这里,只是on_click
).
可在运行时用该信息
正确分发调用
方法,并确保统一表示T
.因此,只编译一次Button
.
多用途
1,闭包.
类似ClickCallback
特征,Rust
中的闭包只是特定特征
.深入
2,条件API
.泛型
可有条件地实现特征
:
struct Pair<A, B> { first: A, second: B }
impl<A: Hash, B: Hash> Hash for Pair<A, B> {fn hash(&self) -> u64 {self.first.hash() ^ self.second.hash()}
}
在此,仅当组件实现Hash
时,Pair
类型才实现Hash
,但允许在不同
环境中使用
单个Pair
类型,这样最大化支持每个环境
时API
的可用性.
这在Rust
中很常见,因此内置
了.
#[derive(Hash)]
struct Pair<A, B> { .. }
3,扩展方法.可用Traits
使用新方法
来扩展
(在其他地方定义
的)现有类型,类似C#
的扩展方法.只需在特征
中定义新方法
,为相关
类型提供实现
,就可用该方法
.
4,标记.Rust
有一些"标记类型
":发送,同步,复制,调整(Send, Sync, Copy, Sized)
.这些标记
只是带空体的特征
,然后可在泛型和特征对象
中使用.
可在库中定义标记
,它们会自动
提供#[derive]
风格实现:如,如果所有子类型
都是Send
,则类型
也是.如前,这些标记
可能非常强大:发送(Send)
标记是Rust
保证线安
的方式.
5,重载.Rust
不支持用多个签名
定义相同方法
的传统重载
.但是trait
提供了重载
的大部分好处:如果在trait
上泛型
定义了方法,则实现该trait
的类型都可调用
它.
与传统
重载相比,有两个优点
.首先,即重载
不是临时的:一旦理解
了一个特征
,就会立即理解使用
它的API
的重载模式
.
其次,它是可扩展
的:通过提供新的特征
实现,可有效
地在方法下游
提供新的重载
.
6,符号.Rust
允许在自己类型
上重载+
等符号.由相应标准库
特征定义每个符号
,实现该特征
类型也会自动
提供符号.
相关文章:
2311rust特征
Rust无成本抽象 Rust中抽象基石是trait: 1,Trait是Rust中唯一的接口概念.多个类型可实现一个特征,事实上,可为现有类型提供新的特征实现.另一方面,想抽象未知类型时,找特征就行了. 2,与C模板一样,可静态分发特征. 3,可动态分发特征.有时确实需要间接,所以不必运行时"擦除…...

原型模式 rust和java的实现
文章目录 原型模式介绍优点缺点使用场景 实现java 实现rust 实现 rust代码仓库 原型模式 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。 这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当…...

阿里云ACK(Serverless)安装APISIX网关及APISIX Ingress Controller
在k8s上安装apisix全家,通过helm安装很简单,但是会遇到一些问题。 安装 首先登录阿里云控制台,在ACK集群详情页,进入CloudShell,执行下面helm命令安装apisix、apisix-ectd、apisix-dashboard和apisix-ingress-contro…...

vue+mongodb+nodejs实现表单增删改查
ExpressMongodbVue实现增删改查 效果图 前言 最近一直想学下node,毕竟会node的前端更有市场。但是光看不练,感觉还是少了点什么,就去github上看别人写的项目,收获颇丰,于是准备自己照葫芦画瓢写一个。 作为程序员,一…...

SpringBootWeb案例——Tlias智能学习辅助系统(3)——登录校验
前一节已经实现了部门管理、员工管理的基本功能。但并没有登录,就直接访问到了Tlias智能学习辅助系统的后台,这节来实现登录认证。 目录 登录功能登录校验(重点)会话技术会话跟踪方案一 Cookie(客户端会话跟踪技术)会话跟踪方案二…...

hive和spark-sql中 日期和时间相关函数 测试对比
测试版本: hive 2.3.4 spark 3.1.1 hadoop 2.7.7 1、增加月份 add_months(timestamp date, int months)add_months(timestamp date, bigint months)Return type: timestampusage:add_months(now(),1) 2、增加日期 adddate(timestamp startdate, int days)…...

Cell和RefCell
Cell和RefCell CellRefCellRefCell在运行时记录借用结合Rc和RefCell来拥有多个可变数据所有者引用循环与内存泄漏制造引用循环避免引用循环:将Rc变为Weak创建树形数据结构:带子节点的Node增加从子到父的引用可视化strong_count 和 weak_count 的改变 Rus…...
DaoWiki(基于Django)开发笔记 20231113
DaoWiki(基于Django)开发笔记 20231113 开发环境 操作系统 windows11python版本 3.12.0django版本 4.2.7 构建python虚拟环境 python -m venv daowiki启动python虚拟环境 cd daowiki\Scripts .\activate安装Django pip install django4.2.7创建项目…...

照片放大软件 Topaz Gigapixel AI mac中文版简介
Topaz Gigapixel AI mac是一款使用人工智能功能扩展图像的桌面应用程序,同时添加自然细节以获得惊人的效果。使用深度学习技术,A.I.Gigapixel™可以放大图像并填写其他调整大小的产品遗漏的细节,使用A.I.Gigapixel™,您可以裁剪照…...

某手游完整性校验分析
前言 只是普通的单机手游,广告比较多,所以分析处理了下,校验流程蛮有意思的,所以就分享出来了 1.重打包崩溃处理 样本进行了加固,对其dump出dex后重打包出现崩溃 ida分析地址发现为jni函数引起 利用Xposed直接替换…...

【ElasticSearch】学习使用DSL和RestClient编写查询语句
文章目录 DSL和RestClient的学习前言1、DSL查询文档1.1 查询分类1.2 全文检索查询1.21 全文检索概述1.2.2 基本使用 1.3 精确查询1.3.1 term查询1.3.2 range查询 1.4 地理坐标查询1.4.1 geo_bounding_box查询1.4.2 geo_distance查询 1.5 复合查询1.5.1 常见相关性算法1.5.2 算分…...

asp.net外卖网站系统VS开发mysql数据库web结构c#编程Microsoft Visual Studio
一、源码特点 asp.net外卖网站系统 是一套完善的web设计管理系统,系统采用mvc模式(BLLDALENTITY)系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为mysql,使用c#语…...

2.4.0 Milky Way 强势登场!新功能大爆炸,让你High翻全场!
Yo开发达人们,我们有重磅新功能要给你们放送啦! Check it out 数据汇总不再单调,新的聚合函数登场! compact_state_agg #1359gauge_agg #1370first #1395last #1413mode #1440increase #1476delta #1395time_delta #1405rate #14…...

C语言----静态链接库和动态链接库
在前面的文章中讲到可执行程序的生成需要经过预处理,编译,汇编和链接四个步骤,链接阶段是链接器将该目标文件与其他目标文件、库文件、启动文件等链接起来生成可执行文件。 需要解读一下库文件,我们可以将库文件等价为压缩包文件&…...

PCA(主成分分析)数据降维技术代码详解
引言 随着大数据时代的到来,我们经常会面临处理高维数据的问题。高维数据不仅增加了计算复杂度,还可能引发“维度灾难”。为了解决这一问题,我们需要对数据进行降维处理,即在不损失太多信息的前提下,将数据从高维空间…...

Git版本控制系统之分支与标签(版本)
目录 一、Git分支(Branch) 1.1 分支作用 1.2 四种分支管理策略 1.3 使用案例 1.3.1 指令 1.3.2 结合应用场景使用 二、Git标签(Tag) 2.1 标签作用 2.2 标签规范 2.3 使用案例 2.3.1 指令 2.3.2 使用示例 一、Git分支&…...

JSP运行环境搭建
将安装JSP引擎的计算机称作一个支持JSP的Web服务器。这个服务器负责运行JSP,并将运行结果返回给用户。 JSP的核心内容之一就是编写JSP页面,JSP页面是Web应用程序的重要组成部分之一。一个简单Web应用程序可能只有一个JSP页面,而一个复杂的Web应用程序可能由许多JSP…...
React通过属性 (props) 和状态 (state) 来传递和管理组件的数据
import React, { useState } from react;// 子组件 const ChildComponent (props) > {return (<div><h2>Hello, {props.name}!</h2></div>); }// 父组件 const ParentComponent () > {const [name, setName] useState(John Doe);const handle…...
Web相机和浏览器的二维码扫描方案
Web相机和适用于浏览器的二维码扫描方案 qr-camera 在线体验 | English 功能 支持浏览器扫描二维码支持拍照支持录像功能支持二维码解析和生成 quickstart npm i qr-cameraimport {QRCamera} from qr-camera;function main(){const camera new QRCamera();document.body…...

云端部署ChatGLM-6B
大模型这里更新是挺快的,我参考的视频教程就和我这个稍微有些不一样,这距离教程发布只过去4天而已… 不过基本操作也差不多 AutoDL算力云:https://www.autodl.com/home ChatGLM3:https://github.com/THUDM/ChatGLM3/tree/main Hug…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
Pydantic + Function Calling的结合
1、Pydantic Pydantic 是一个 Python 库,用于数据验证和设置管理,通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发(如 FastAPI)、配置管理和数据解析,核心功能包括: 数据验证:通过…...
Vue 3 + WebSocket 实战:公司通知实时推送功能详解
📢 Vue 3 WebSocket 实战:公司通知实时推送功能详解 📌 收藏 点赞 关注,项目中要用到推送功能时就不怕找不到了! 实时通知是企业系统中常见的功能,比如:管理员发布通知后,所有用户…...

Element-Plus:popconfirm与tooltip一起使用不生效?
你们好,我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip,产品要求是两个需要结合一起使用,也就是鼠标悬浮上去有提示文字,并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…...
【Java】Ajax 技术详解
文章目录 1. Filter 过滤器1.1 Filter 概述1.2 Filter 快速入门开发步骤:1.3 Filter 执行流程1.4 Filter 拦截路径配置1.5 过滤器链2. Listener 监听器2.1 Listener 概述2.2 ServletContextListener3. Ajax 技术3.1 Ajax 概述3.2 Ajax 快速入门服务端实现:客户端实现:4. Axi…...

从0开始学习R语言--Day17--Cox回归
Cox回归 在用医疗数据作分析时,最常见的是去预测某类病的患者的死亡率或预测他们的结局。但是我们得到的病人数据,往往会有很多的协变量,即使我们通过计算来减少指标对结果的影响,我们的数据中依然会有很多的协变量,且…...