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

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

泛型概述 , 如何定义泛型函数

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 . 泛型的定义 在仓颉编程语言中&#xff0c;泛型机制允许我们定义参数化类型&#xff0c;这些类型在声明时不具体指定其操作的数据类型&#xff0c;而是作为类型形参保留&#xff0c;待使用时通过类型实参来明确。这种灵活性在函数和类型声明中…...

SOC估算方法之(OCV-SOC+安时积分法)

一、引言 此方法主要参考电动汽车用磷酸铁锂电池SOC估算方法这篇论文 总结&#xff1a; 开路电压的测量需要将电池静止相当长的一段时间才能达到平衡状态进行测量。 安时积分法存在初始SOC的估算和累积的误差。 所以上述两种方法都存在一定的缺陷&#xff0c;因此下面主要讲…...

指针(下)

文章目录 指针(下)野指针、空指针野指针空指针 二级指针**main**函数的原型说明 常量指针与指针常量常量指针指针常量常量指针常量 动态内存分配常用函数**malloc****calloc****realloc****free** **void**与**void***的区别扩展&#xff1a;形式参数和实际参数的对应关系 指针…...

C# 浅谈IEnumerable

一、IEnumerable 简介 IEnumerable 是一个接口&#xff0c;它定义了对集合进行迭代所需的方法。IEnumerable 接口主要用于允许开发者使用foreach循环来遍历集合中的元素。这个接口定义了一个名为 GetEnumerator 的方法&#xff0c;该方法返回一个实现了 IEnumerator 接口的对象…...

mmdebstrap:创建 Debian 系统 chroot 环境的利器 ️

文章目录 mmdebstrap 的一般性参数说明 &#x1f4dc;mmdebstrap 的常见用法示例 &#x1f308;使用 mmdebstrap 的注意事项 ⚠️ &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界&#xff0c;能与您在此邂逅&#xff0c;真是缘分使然&am…...

【Linux SQLite数据库】一、SQLite交叉编译与移植

SQLite 是一个用 C 语言编写的开源、轻量级、快速、独立且高可靠性的 SQL 数据库引擎&#xff0c;它提供了功能齐全的数据库解决方案。SQLite 几乎可以在所有的手机和计算机上运行&#xff0c;它被嵌入到无数人每天都在使用的众多应用程序中。此外&#xff0c;SQLite 还具有稳定…...

每天写两道(数组篇)移除元素、

27.移除元素 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k&#xff0c;要通过此题&#xff0c;您需要执行以下操作&#…...

Unity 使用 NewtonSoft Json插件报错

JsonReaderException: Unexpected character encountered while parsing value: . Path , line 0, position 0. 通过断点发现&#xff0c;头有一串ZWNBSP&#xff0c;这个是BOM格式的JSON。在文件下看不到。 解决方法&#xff1a;改编码格式&#xff0c;Remove BOM....

k8s 部署 Mysqld_exporter 以及添加告警规则

最近监控 mysql 数据库&#xff0c;用了 pmm-server、pmm-client 发现监控是真的不太好用&#xff0c;还是用回 prometheus 吧。 部署mysqld_exporter k8s 部署最新版本的 mysqld_exporter&#xff0c;支持的数据库版本 MySQL >5.6、MariaDB > 10.3。 先在数据库创建用…...

基于STM32开发的智能农业环境监测系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 初始化代码控制代码应用场景 农田环境监测温室环境控制常见问题及解决方案 常见问题解决方案结论 1. 引言 智能农业环境监测系统通过集成多种环境传感器&#xff0c;实时监测土壤湿度、温度…...

【SQL】平均售价

目录 题目 分析 代码 题目 表&#xff1a;Prices ------------------------ | Column Name | Type | ------------------------ | product_id | int | | start_date | date | | end_date | date | | price | int | ---------------…...

存储器与CPU的连接

1.单块存储芯片与CPU的连接 单独的一块独立的存储芯片提供的线有&#xff1a;地址总线&#xff0c;数据总线&#xff0c;读写控制线&#xff0c;片选线&#xff0c;如果该存储器只有八根数据总线用于输出数据&#xff0c;而cpu一次可以读64位的数据呢&#xff1f; 我们可以将八…...

unity--webgl 访问本地index.html

目录 1:使用本地服务器 1.1 使用 Python 的 SimpleHTTPServer 1.2 使用 Node.js 的 http-server 2&#xff1a;让其他人通过 IP 地址来访问你的 Unity WebGL 项目 2.1: 确保服务器可访问 2.2 获取公共 IP 地址 2.3 配置本地服务器 1.使用 Python 的 SimpleHTTPServer 2…...

慢慢欣赏DPDK RTE_MAX_ETHPORTS的定义

DPDK代码里面&#xff0c;RTE_MAX_ETHPORTS是一个常见的宏定义&#xff0c;但是在.c和.h文件找不到其定义&#xff0c;在全文件搜索条件下&#xff0c;在config/meson.build找到这么一个定义 dpdk_conf.set(RTE_MAX_ETHPORTS, get_option(max_ethports)) 该宏定义是根据构建输…...

Java Nacos与Gateway的使用

Java系列文章目录 IDEA使用指南 Java泛型总结&#xff08;快速上手详解&#xff09; Java Lambda表达式总结&#xff08;快速上手详解&#xff09; Java Optional容器总结&#xff08;快速上手图解&#xff09; Java 自定义注解笔记总结&#xff08;油管&#xff09; Jav…...

前端项目中的Server-sent Events(SSE)项目实践及其与websocket的区别

前端项目中的Server-sent Events(SSE)项目实践 前言 在前端开发中&#xff0c;实时数据更新是提升用户体验的重要因素之一。Server-SentEvents(SSE)是一种高效的技术&#xff0c;允许服务器通过单向连接将实时数据推送到客户端。下面将从SSE的基本改变&#xff0c;使用场景展…...

《老俞闲话|唯爱和热情不可辜负》读后感

《老俞闲话&#xff5c;唯爱和热情不可辜负》读后感 俞敏洪先生的这篇讲话充满了深情与智慧&#xff0c;他以自己丰富的人生经历和教育实践&#xff0c;向我们展现了一位教育家对于教育事业的热爱和对教师角色的深刻理解。 情感真挚&#xff0c;触动人心 俞敏洪先生的讲话中流…...

C语言 ——— 在杨氏矩阵中查找具体的某个数

目录 何为杨氏矩阵 题目要求 代码实现 何为杨氏矩阵 可以把杨氏矩阵理解为一个二维数组&#xff0c;这个二维数组中的每一行从左到右是递增的&#xff0c;每一列从上到下是递增的 题目要求 在杨氏矩阵中查找具体的某个数 要求&#xff1a;时间复杂度小于O(N) 代码实现…...

DAI-Net: 基于对偶自适应交互网络的药物推荐算法

引言 DAI-Net: Dual Adaptive Interaction Network for Coordinated Medication Recommendation 论文链接&#xff1a;https://ieeexplore.ieee.org/document/10614809 代码链接&#xff1a;GitHub - obananas/DAI-Net 在现代医疗保健中&#xff0c;如何利用电子健康记录&a…...

haproxy高级功能及配置

章节 一、haproxy 基础用法 二、haproxy 高级用法 三、haproxy之ACL的使用 目录 1 基于cookie的会话保持 1.1 cookie命名&#xff0c;并赋予其值 1.2 验证cookie信息 1.2.1 Windows浏览器验证 1.2.2 Linux下虚拟机验证 2 IP透传 2.1 四层与七层透传的区别 2.2 七层IP透传 2.2…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...