当前位置: 首页 > news >正文

2311rust特征

Rust无成本抽象

Rust中抽象基石是trait:
1,TraitRust中唯一的接口概念.多个类型可实现一个特征,事实上,可为现有类型提供新的特征实现.另一方面,想抽象未知类型时,找特征就行了.
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特征.即可与booli64值一起,使用它:

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.
然后,可定义一个在实现哈希EqT类型上是都通用的哈希映射:

struct HashMap<Key: Hash + Eq, Value> { ... }

泛型静态编译模型有几个好处:
1,对具体的KeyValue类型,每次使用HashMap都会产生不同的具体HashMap类型,即HashMap可在其存储桶内联(无间接)布局键和值.
来可节省空间和间接,并提高缓存局部性.

2,HashMap上的每个方法同样会生成特化代码.即,如上,调用哈希Eq,不会产生额外成本.表明优化器可用最具体(也即没有抽象)的代码.
特别是,静态分发允许在泛型用法间内联.
总之,与在C++模板一样,你可用泛型编写无成本的相当高级的抽象.
但是,与C++模板不同的是,会提前完全类型检查特征客户.也即,单独编译HashMap时,会根据抽象HashEq特征检查一次代码类型正确性,而不是在每当应用具体类型时的重复检查.

即库作者可更早,更清晰地出现编译错误,而客户类型检查成本更少(即编译速度更快).

动态分发

有时,抽象不仅是重用或模块化,有时在运行时不能去掉抽象.
如,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中,像&ClickCallbackBox<ClickCallback>的类型叫"trait对象",它包括指向实现ClickCallbackT类型实例的指针,及一个虚表:一个指向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代码仓库 原型模式 原型模式&#xff08;Prototype Pattern&#xff09;是用于创建重复的对象&#xff0c;同时又能保证性能。 这种模式是实现了一个原型接口&#xff0c;该接口用于创建当前对象的克隆。当…...

阿里云ACK(Serverless)安装APISIX网关及APISIX Ingress Controller

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

vue+mongodb+nodejs实现表单增删改查

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

SpringBootWeb案例——Tlias智能学习辅助系统(3)——登录校验

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

hive和spark-sql中 日期和时间相关函数 测试对比

测试版本&#xff1a; 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来拥有多个可变数据所有者引用循环与内存泄漏制造引用循环避免引用循环&#xff1a;将Rc变为Weak创建树形数据结构&#xff1a;带子节点的Node增加从子到父的引用可视化strong_count 和 weak_count 的改变 Rus…...

DaoWiki(基于Django)开发笔记 20231113

DaoWiki&#xff08;基于Django&#xff09;开发笔记 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是一款使用人工智能功能扩展图像的桌面应用程序&#xff0c;同时添加自然细节以获得惊人的效果。使用深度学习技术&#xff0c;A.I.Gigapixel™可以放大图像并填写其他调整大小的产品遗漏的细节&#xff0c;使用A.I.Gigapixel™&#xff0c;您可以裁剪照…...

某手游完整性校验分析

前言 只是普通的单机手游&#xff0c;广告比较多&#xff0c;所以分析处理了下&#xff0c;校验流程蛮有意思的&#xff0c;所以就分享出来了 1.重打包崩溃处理 样本进行了加固&#xff0c;对其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设计管理系统&#xff0c;系统采用mvc模式&#xff08;BLLDALENTITY&#xff09;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为mysql&#xff0c;使用c#语…...

2.4.0 Milky Way 强势登场!新功能大爆炸,让你High翻全场!

Yo开发达人们&#xff0c;我们有重磅新功能要给你们放送啦&#xff01; Check it out 数据汇总不再单调&#xff0c;新的聚合函数登场&#xff01; compact_state_agg #1359gauge_agg #1370first #1395last #1413mode #1440increase #1476delta #1395time_delta #1405rate #14…...

C语言----静态链接库和动态链接库

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

PCA(主成分分析)数据降维技术代码详解

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

Git版本控制系统之分支与标签(版本)

目录 一、Git分支&#xff08;Branch&#xff09; 1.1 分支作用 1.2 四种分支管理策略 1.3 使用案例 1.3.1 指令 1.3.2 结合应用场景使用 二、Git标签&#xff08;Tag&#xff09; 2.1 标签作用 2.2 标签规范 2.3 使用案例 2.3.1 指令 2.3.2 使用示例 一、Git分支&…...

JSP运行环境搭建

将安装JSP引擎的计算机称作一个支持JSP的Web服务器。这个服务器负责运行JSP&#xff0c;并将运行结果返回给用户。 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

大模型这里更新是挺快的&#xff0c;我参考的视频教程就和我这个稍微有些不一样&#xff0c;这距离教程发布只过去4天而已… 不过基本操作也差不多 AutoDL算力云&#xff1a;https://www.autodl.com/home ChatGLM3&#xff1a;https://github.com/THUDM/ChatGLM3/tree/main Hug…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

Pydantic + Function Calling的结合

1、Pydantic Pydantic 是一个 Python 库&#xff0c;用于数据验证和设置管理&#xff0c;通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发&#xff08;如 FastAPI&#xff09;、配置管理和数据解析&#xff0c;核心功能包括&#xff1a; 数据验证&#xff1a;通过…...

Vue 3 + WebSocket 实战:公司通知实时推送功能详解

&#x1f4e2; Vue 3 WebSocket 实战&#xff1a;公司通知实时推送功能详解 &#x1f4cc; 收藏 点赞 关注&#xff0c;项目中要用到推送功能时就不怕找不到了&#xff01; 实时通知是企业系统中常见的功能&#xff0c;比如&#xff1a;管理员发布通知后&#xff0c;所有用户…...

Element-Plus:popconfirm与tooltip一起使用不生效?

你们好&#xff0c;我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip&#xff0c;产品要求是两个需要结合一起使用&#xff0c;也就是鼠标悬浮上去有提示文字&#xff0c;并且点击之后需要出现气泡确认框 代码 <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回归 在用医疗数据作分析时&#xff0c;最常见的是去预测某类病的患者的死亡率或预测他们的结局。但是我们得到的病人数据&#xff0c;往往会有很多的协变量&#xff0c;即使我们通过计算来减少指标对结果的影响&#xff0c;我们的数据中依然会有很多的协变量&#xff0c;且…...