【Lua学习笔记】Lua进阶——函数和闭包

文章目录
- 函数
- 函数嵌套
- 闭包Closures
- 可变函数
- 函数重载
函数
函数嵌套
function A()print("这里是函数A")return function ()print("返回函数不要起名")end
end
B = A()
B()输出:
这里是函数A
返回函数不要起名
使用函数嵌套的用法,我们可以将另一个函数作为返回值,但是返回函数作为一个值是要被赋值给其他变量的,所以return时不能起名(赋值)为其他变量名。
闭包Closures
推荐阅读深入Lua:函数和闭包
在函数嵌套中,我们需要接触一个叫做闭包的概念
这就是一个闭包,它由一个函数和该函数会访问到的非局部变量(或者说upvalue)组成
function f1(n)--函数参数n也是局部变量local function f2()print(n) --引用外部函数的局部变量,即upvalueendreturn f2
enda =f1(1) --注意,闭包不传入参数则为nil
a()
当一个函数内嵌套另一个函数的时候,内函数可以访问外部函数的局部变量,这种特征被称为词法域,什么意思呢?
例如上述f1的入参n,它是一个形参,也是f1内的局部变量。现在f1内部定义了另一个函数f2,显然f2需要访问f1内的局部变量 n。但是对于n而言,它的词法域或者说作用域只是在f1内。如果只是简单的函数嵌套的话,用其他语言可以是这样实现的:
void f1(int x){f2(x)
}
void f2(int x){return x
}
但是问题是上述定义中f1内的x和f2内的x并不是同一个x,而分别是它们作用域内定义的局部变量。
而闭包更相当于一个指针,使得f2直接引用了f1的局部变量
#include <iostream>
using namespace std;
void f2(int *x)
{printf("%d", *x);
}
void f1(int x)
{f2(&x);
}
int main()
{int i = 1;f1(i);return 0;
}
这就是闭包的概念:内部函数innerFunction能够访问并持有其外部函数outerFunction作用域中的变量,这些被内部函数引用的外部函数的局部变量被称为upvalues。实际上,一般的函数在lua中是一种特殊的闭包。整个函数产生的闭包类似于下列struct :
// Lua闭包
typedef struct LClosure {ClosureHeader;struct Proto *p; // 函数原型UpVal *upvals[1]; /* list of upvalues */ // upvalue列表
} LClosure;
function Create(n)local function f1()print(n)endlocal function f2()n = n + 10endreturn f1,f2
end
a,b = Create(10)
a() -- 10
b()
a() -- 20
b()
a() -- 30
在上述闭包中,两个闭包f1,f2使用的n是同一个局部变量,因此f2使n增加后,f1输出值也变了。它们共享一个upvalues。
现在假设要创建一个对象,对外只提供有限的访问接口,而对象内部的数据不能直接被修改,那么我们可以这样写:
local function new_object()local obj = { -- 这就是要创建的对象_data1 = 1, -- 假设这是内部数据_data2 = 2, -- 这是外部可修改的数据}return { -- 这是返回的接口tableget_data2 = function() return obj._data2 end,set_data2 = function(value) obj._data2 = value end,}
endlocal obj_inteface = new_object()
obj_inteface.set_data2(100)
print(obj_inteface.get_data2()) --> 100
可变函数
function f1( x,...)arg={...}for i=1,#arg doprint(arg[i])end
end
我们用…表示参数是可变参数,它能接收任意长的参数,但是在我们使用的时候,最好使用一个table来接收这个可变参数。此外其他固定的入参一定要放在可变参数的前面,这样函数才能先接受入参,其他的丢给可变参数。
函数重载
function A()print(123)
end
A()function A(a)print(a)
end
A(1)输出:
123
1
在Lua中,函数的重载十分简单,只需在函数下方重写这个函数即可。在Unity中Lua能实现热更新,例如修正一些Bug,就是通过重载函数实现的,举个例子:
摘自Lua语言:函数级别的重载
-- hotfix.lua
--- 执行热更新
-- oldmod是旧模块
-- newmod是新模块,这个模块里只会提供要替换的函数,相当于旧模块的一个子集。
function hotfix.run(oldmod, newmod)-- 收集旧模块的所有upvaluelocal uvmap = collect_all_upvalue(oldmod)for k, v in pairs(newmod) doif type(v) == 'function' then-- 这里就是先把新函数的upvalue修正,然后直接替换给旧模块oldmod[k] = hotfix_func(v, uvmap)endend
end
return hotfix
相关文章:
【Lua学习笔记】Lua进阶——函数和闭包
文章目录 函数函数嵌套闭包Closures可变函数函数重载 函数 函数嵌套 function A()print("这里是函数A")return function ()print("返回函数不要起名")end end B A() B()输出: 这里是函数A 返回函数不要起名使用函数嵌套的用法,我…...
大学生竞赛管理系统springboot比赛报名信息java jsp源代码mysql
本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 大学生竞赛管理系统springboot 系统有3权限ÿ…...
UnixBench 5.1.3 银河麒麟桌面操作系统V10 (SP1) ARM64 aarch64 图形性能测试 2d 3d, glmark2 3d测试
编译 安装libgl sudo apt install libgl-dev yeqiangyeqiang-greatwall:~/Downloads/UnixBench$ sudo apt install libgl-dev [sudo] yeqiang 的密码: 正在读取软件包列表... 完成 正在分析软件包的依赖关系树 正在读取状态信息... 完成 下列软件包…...
JavaScript高级——ES6基础入门
目录 前言let 和 const块级作用域模板字符串一.模板字符串是什么二.模板字符串的注意事项三. 模板字符串的应用 箭头函数一.箭头函数是什么二.普通函数与箭头函数的转换三.this指向1. 全局作用域中的 this 指向2. 一般函数(非箭头函数)中的this指向3.箭头…...
2023年超越期待的高性能视频剪辑主机推荐| Intel 蝰蛇峡谷测评
1、开箱 蝰蛇峡谷的开箱体验是非常令人兴奋的。首先,打开包装后,你会看到一个精致且高质感的机箱,给人一种专业的感觉。蝰蛇峡谷的外观设计简洁大方,黑色的机箱与红色的Logo相得益彰,展现了其高性能的特点。 在打开机…...
1400*A. Factory
Examples input 1 5 output No input 3 6 output Yes 题意: a 和 m,a 不断加 a%m ,如果 a 有一次能够被 m 整除,则打印 Yes,如果一直循环永远不可能被 m 整除,则打印 No 解析: 可以观…...
OpenHarmony开源鸿蒙学习入门 - 基于3.2Release 应用开发环境安装
OpenHarmony开源鸿蒙学习入门 - 基于3.2Release 应用开发环境安装 基于目前官方master主支,最新文档版本3.2Release,更新应用开发环境安装文档。 一、安装IDE: 1.IDE安装的系统要求 2.IDE下载官网链接(IDE下载链接) …...
Linux 查看服务器内存、CPU、网络等占用情况的命令
1、查看物理CPU个数:cat cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l 2、查看服务器CPU内核个数:cat 每个物理CPU中core的个数(即核数) cat /proc/cpuinfo | grep "cpu cores" | u…...
调用webservice导excel文件内容进入数据库
一个早期vb.net写的程序,需要增加功能,要导入excel数据,并按条件显示。 1.数据库端 1.1因为是要把表作为存储过程的输入参数,所以先新建一个数据类型xtabletype create type xtabletype as table(prodid varchar(20),itemid varchar(20),target varchar(150)) 1.2新建…...
*CTF 2023 web jwt2struts 题解wp
jwt2struts 根据题目名字猜测,这题考察jwt和Struts2 包里面果然有一个cookie 验证了,是jwt eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiZXhwIjoyMDA2MjI1MjgxfQ.F7vOtdqg48M1DYK4tVZywTipIYDqKfsBSju7ekLSecU 我们的目标应该是把user改…...
使用java实时获取手环、手表的健康数据
吐槽 最近在自研开发一款有关读取健康数据的APP 但是数据来源非常稀少,申请了市面上所有的国内厂商的手环api都被拒了(因为是个人开发) 找了很久发现fitbit有开源的api于是淘了个fitbit的手表开始开发 Web API (fitbit.com) 在上述连接可…...
Maven右侧依赖Dependencies消失
项目右侧的Maven依赖Dependencies突然消失,项目中的注解都出现报错,出现这种情况应该是因为IDEA版本早于maven版本,重新检查项目中的Maven路径,选择File->Settings->搜索Maven,检查Maven home directory…...
100% RNN language model ChatRWKV 相关开源项目
RWKV(读作RwaKuv)借鉴了RNN的移动平均模型(MA),将transformer的 O ( T 2 d ) O(T^2d) O(T2d)复杂度降低到 O ( T d ) O(Td) O(Td),同时保持较好的结果表现。RWKV也是一个开源模型,甚至其介绍主页的html代码都有开源。以…...
ElasticSearch Window Linux部署
文章目录 一、Window 集群部署二、Linux 单节点部署三、Linux 集群部署 一、Window 集群部署 创建 elasticsearch-cluster 文件夹,在内部复制三个elasticsearch服务 修改集群文件目录中每个节点的 config/elasticsearch.yml 配置文件 # -----------------------…...
MyBatis-Plus 分页插件实现分页查询
目录 1. 配置分页查询的拦截器 2. 使用 Page 对象实现分页功能 1. 配置分页查询的拦截器 因为 MyBatis-Plus 里面使用了分页插件来实现分页查询, 所以我们需要将 MyBatis-Plus 的插件添加到当前的项目里, 这样我们执行的查询操作才会生效. 创建 PageConfig 类: Configurat…...
Nacos源码 (1) 源码编译及idea环境
本文介绍从gitee下载nacos源码,在本地编译,并导入idea进行本地调试。 从gitee下载源码 由于github访问速度慢,所以我选择使用gitee的镜像仓库: git clone https://gitee.com/mirrors/Nacos.git本文使用2.0.2版本,所…...
docker配置文件挂载(容器数据管理)
目录 数据卷(容器数据管理)什么是数据卷数据集操作命令创建和查看数据卷挂载数据卷案例案例-给nginx挂载数据卷案例-给MySQL挂载本地目录 总结 数据卷(容器数据管理) 在之前的nginx案例中,修改nginx的html页面时&#…...
uniAPP 视频图片预览组件
效果图 思路:处理文件列表,根据文件类型归类 已兼容 H5 ios 设备,测试已通过 浙政钉,微信小程序 视频资源因为,没有预览图,用灰色图层加播放按钮代替 <template><!--视频图片预览组件 -->&l…...
【论文阅读】The Deep Learning Compiler: A Comprehensive Survey
论文来源:Li M , Liu Y , Liu X ,et al.The Deep Learning Compiler: A Comprehensive Survey[J]. 2020.DOI:10.1109/TPDS.2020.3030548. 这是一篇关于深度学习编译器的综述类文章。 什么是深度学习编译器 深度学习(Deep Learning)编译器将…...
怎么维护自己的电脑?
方向一:我的电脑介绍 我使用的是一台来自知名品牌的笔记本电脑。它具有高性能的核心配置,如快速处理器、大容量内存和高性能显卡,以及宽敞的存储空间。我选择这台电脑主要是因为它的出色性能和可靠性,能够满足我在学习和工作中的…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
