仓颉编程入门 -- 泛型概述 , 如何定义泛型函数
泛型概述 , 如何定义泛型函数
1 . 泛型的定义

在仓颉编程语言中,泛型机制允许我们定义参数化类型,这些类型在声明时不具体指定其操作的数据类型,而是作为类型形参保留,待使用时通过类型实参来明确。这种灵活性在函数和类型声明中尤为常见,如Array和Set等容器类型就是典型的泛型应用。以数组为例,由于我们可能需要在数组中存储多种不同类型的数据,因此不可能为每种数据类型都定义一个专门的数组类型。通过引入泛型,我们可以在数组类型声明时声明一个或多个类型形参(如T),并在实际使用数组时指定这些形参的具体类型,从而避免了代码的大量重复。
在仓颉编程语言的体系中,不仅函数声明可以是泛型的,就连class、interface、struct以及enum的声明也都可以声明类型形参,即它们都可以被设计为泛型。为了更清晰地讨论这一机制,我们引入了几个关键术语:类型形参用于在声明时占位,等待具体类型的填充;类型变元则是在声明体中引用这些形参的标识符;类型实参则是在实际使用泛型类型或函数时提供的具体类型;而类型构造器则是指那些需要接收类型实参以完成其定义的类型。
综上所述,泛型在仓颉编程语言中是一种强大的工具,它允许我们在不牺牲类型安全的前提下,编写出更加灵活和可复用的代码。通过声明所要使用对象的类型(以类型形参的形式),并在使用时指定具体的类型实参,我们能够实现代码的泛型化,减少重复,提高开发效率。
2 . 如何声明泛型
在声明类型或函数时,类型形参通常会被放置在类型名称或函数名称之后,并使用尖括号<…>来包围,以明确标识出这些形参的存在。例如,一个泛型列表(在支持泛型的编程语言中)可以被声明为在列表类型名称后紧跟尖括号,并在尖括号内指定一个或多个类型形参,如List所示,其中T就是一个类型形参的标识符。
class List<T> {var elem: Option<T> = Nonevar tail: Option<List<T>> = None
}
在List的声明中,T被称为类型形参,它代表了一个在声明时未具体指定,而在使用时需要被替换为具体类型的占位符。对于表达式如elem: Option中的T,以及tail: Option<List>中的T,这些在泛型类型内部被引用的标识符被称为类型变元,因为它们代表了类型形参在泛型类型定义中的具体引用点。
当我们在函数或变量声明中实际使用泛型类型时,如sumInt函数的参数List,其中的Int64就被称为List的类型实参。这些类型实参是在使用泛型类型时提供的具体类型,它们替代了泛型声明中的类型形参,从而构造出了具体的类型实例。
List本身在这里被视为一个类型构造器,因为它是一个需要类型实参来构造出具体类型的泛型类型。通过提供Int64作为类型实参给List,我们构造出了一个专门用于存储Int64类型元素的列表类型,即List。这个过程展示了泛型类型如何通过类型实参的替换来生成具体的、可操作的类型实例。
3. 全局泛型函数
在声明全局泛型函数时,只需要在函数名后使用尖括号声明类型形参,然后就可以在函数形参、返回类型及函数体中对这一类型形参进行引用。例如 id 函数定义为:
func id<T>(a: T): T {return a
}
在这里,我们定义了一个名为id的泛型函数,该函数声明了一个名为a的变量作为形参,其类型由泛型类型形参T指定。a: T是函数id的形参声明,其中T是id函数声明的类型形参,它用于在函数体内引用和操作a,同时也决定了id函数的返回类型(通常id函数会返回其输入参数,因此返回类型也是T)。
接下来,考虑一个更复杂的泛型函数定义,名为composition。这个函数声明了三个类型形参:T1、T2、和T3。composition的功能是将两个函数复合成一个新的函数。具体而言,它接受两个函数f和g作为参数,其中f是一个从T1类型到T2类型的函数(即f: (T1) -> T2),而g是一个从T2类型到T3类型的函数(即g: (T2) -> T3)。通过这两个函数的组合,composition函数生成了一个新的函数,该函数的类型是从T1到T3的(即(T1) -> T3),它首先应用f函数到其输入上,然后将f的输出作为g的输入,最后返回g的输出。这样,composition函数实现了两个函数的串联调用。
func composition<T1, T2, T3>(f: (T1) -> T2, g: (T2) -> T3): (T1) -> T3 {return {x: T1 => g(f(x))}
}
因为被用来复合的函数可以是任意类型,例如可以是 (Int32) -> Bool, (Bool) -> Int64 的复合,也可以是 (Int64) -> Rune, (Rune) -> Int8 的复合,所以才需要使用泛型函数。
func times2(a: Int64): Int64 {return a * 2
}func plus10(a: Int64): Int64 {return a + 10
}func times2plus10(a: Int64) {return composition<Int64, Int64, Int64>(times2, plus10)(a)
}main() {println(times2plus10(9))return 0
}
4. 局部泛型函数
简单来说局部泛型函数就是在一个函数中嵌套另一个泛型函数
func foo(a: Int64) {func id<T>(a: T): T { a }func double(a: Int64): Int64 { a + a }return (id<Int64> ~> double)(a) == (double ~> id<Int64>)(a)
}main() {println(foo(1))return 0
}
相关文章:
仓颉编程入门 -- 泛型概述 , 如何定义泛型函数
泛型概述 , 如何定义泛型函数 1 . 泛型的定义 在仓颉编程语言中,泛型机制允许我们定义参数化类型,这些类型在声明时不具体指定其操作的数据类型,而是作为类型形参保留,待使用时通过类型实参来明确。这种灵活性在函数和类型声明中…...
SOC估算方法之(OCV-SOC+安时积分法)
一、引言 此方法主要参考电动汽车用磷酸铁锂电池SOC估算方法这篇论文 总结: 开路电压的测量需要将电池静止相当长的一段时间才能达到平衡状态进行测量。 安时积分法存在初始SOC的估算和累积的误差。 所以上述两种方法都存在一定的缺陷,因此下面主要讲…...
指针(下)
文章目录 指针(下)野指针、空指针野指针空指针 二级指针**main**函数的原型说明 常量指针与指针常量常量指针指针常量常量指针常量 动态内存分配常用函数**malloc****calloc****realloc****free** **void**与**void***的区别扩展:形式参数和实际参数的对应关系 指针…...
C# 浅谈IEnumerable
一、IEnumerable 简介 IEnumerable 是一个接口,它定义了对集合进行迭代所需的方法。IEnumerable 接口主要用于允许开发者使用foreach循环来遍历集合中的元素。这个接口定义了一个名为 GetEnumerator 的方法,该方法返回一个实现了 IEnumerator 接口的对象…...
mmdebstrap:创建 Debian 系统 chroot 环境的利器 ️
文章目录 mmdebstrap 的一般性参数说明 📜mmdebstrap 的常见用法示例 🌈使用 mmdebstrap 的注意事项 ⚠️ 🌈你好呀!我是 山顶风景独好 🎈欢迎踏入我的博客世界,能与您在此邂逅,真是缘分使然&am…...
【Linux SQLite数据库】一、SQLite交叉编译与移植
SQLite 是一个用 C 语言编写的开源、轻量级、快速、独立且高可靠性的 SQL 数据库引擎,它提供了功能齐全的数据库解决方案。SQLite 几乎可以在所有的手机和计算机上运行,它被嵌入到无数人每天都在使用的众多应用程序中。此外,SQLite 还具有稳定…...
每天写两道(数组篇)移除元素、
27.移除元素 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作&#…...
Unity 使用 NewtonSoft Json插件报错
JsonReaderException: Unexpected character encountered while parsing value: . Path , line 0, position 0. 通过断点发现,头有一串ZWNBSP,这个是BOM格式的JSON。在文件下看不到。 解决方法:改编码格式,Remove BOM....
k8s 部署 Mysqld_exporter 以及添加告警规则
最近监控 mysql 数据库,用了 pmm-server、pmm-client 发现监控是真的不太好用,还是用回 prometheus 吧。 部署mysqld_exporter k8s 部署最新版本的 mysqld_exporter,支持的数据库版本 MySQL >5.6、MariaDB > 10.3。 先在数据库创建用…...
基于STM32开发的智能农业环境监测系统
目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 初始化代码控制代码应用场景 农田环境监测温室环境控制常见问题及解决方案 常见问题解决方案结论 1. 引言 智能农业环境监测系统通过集成多种环境传感器,实时监测土壤湿度、温度…...
【SQL】平均售价
目录 题目 分析 代码 题目 表:Prices ------------------------ | Column Name | Type | ------------------------ | product_id | int | | start_date | date | | end_date | date | | price | int | ---------------…...
存储器与CPU的连接
1.单块存储芯片与CPU的连接 单独的一块独立的存储芯片提供的线有:地址总线,数据总线,读写控制线,片选线,如果该存储器只有八根数据总线用于输出数据,而cpu一次可以读64位的数据呢? 我们可以将八…...
unity--webgl 访问本地index.html
目录 1:使用本地服务器 1.1 使用 Python 的 SimpleHTTPServer 1.2 使用 Node.js 的 http-server 2:让其他人通过 IP 地址来访问你的 Unity WebGL 项目 2.1: 确保服务器可访问 2.2 获取公共 IP 地址 2.3 配置本地服务器 1.使用 Python 的 SimpleHTTPServer 2…...
慢慢欣赏DPDK RTE_MAX_ETHPORTS的定义
DPDK代码里面,RTE_MAX_ETHPORTS是一个常见的宏定义,但是在.c和.h文件找不到其定义,在全文件搜索条件下,在config/meson.build找到这么一个定义 dpdk_conf.set(RTE_MAX_ETHPORTS, get_option(max_ethports)) 该宏定义是根据构建输…...
Java Nacos与Gateway的使用
Java系列文章目录 IDEA使用指南 Java泛型总结(快速上手详解) Java Lambda表达式总结(快速上手详解) Java Optional容器总结(快速上手图解) Java 自定义注解笔记总结(油管) Jav…...
前端项目中的Server-sent Events(SSE)项目实践及其与websocket的区别
前端项目中的Server-sent Events(SSE)项目实践 前言 在前端开发中,实时数据更新是提升用户体验的重要因素之一。Server-SentEvents(SSE)是一种高效的技术,允许服务器通过单向连接将实时数据推送到客户端。下面将从SSE的基本改变,使用场景展…...
《老俞闲话|唯爱和热情不可辜负》读后感
《老俞闲话|唯爱和热情不可辜负》读后感 俞敏洪先生的这篇讲话充满了深情与智慧,他以自己丰富的人生经历和教育实践,向我们展现了一位教育家对于教育事业的热爱和对教师角色的深刻理解。 情感真挚,触动人心 俞敏洪先生的讲话中流…...
C语言 ——— 在杨氏矩阵中查找具体的某个数
目录 何为杨氏矩阵 题目要求 代码实现 何为杨氏矩阵 可以把杨氏矩阵理解为一个二维数组,这个二维数组中的每一行从左到右是递增的,每一列从上到下是递增的 题目要求 在杨氏矩阵中查找具体的某个数 要求:时间复杂度小于O(N) 代码实现…...
DAI-Net: 基于对偶自适应交互网络的药物推荐算法
引言 DAI-Net: Dual Adaptive Interaction Network for Coordinated Medication Recommendation 论文链接:https://ieeexplore.ieee.org/document/10614809 代码链接:GitHub - obananas/DAI-Net 在现代医疗保健中,如何利用电子健康记录&a…...
haproxy高级功能及配置
章节 一、haproxy 基础用法 二、haproxy 高级用法 三、haproxy之ACL的使用 目录 1 基于cookie的会话保持 1.1 cookie命名,并赋予其值 1.2 验证cookie信息 1.2.1 Windows浏览器验证 1.2.2 Linux下虚拟机验证 2 IP透传 2.1 四层与七层透传的区别 2.2 七层IP透传 2.2…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
