Lua程序设计复习笔记

Lua程序设计

  • 程序段:我们将Lua语言执行的每一段代码(例如,一个文件或交互模式下的一行)称为一个程序段(Chunk),即一组命令或表达式组成的序列。

  • 一些词法规范:下划线+大写 是特定变量命名规范

  • 全局变量

  • Boolean类型:逻辑运算符 and or not;利用短路原则 a = x or 1;
    a > b and a or b,相当于C语言中 a >b ?a: b; not 运算符永远返回true or false

  • 独立解释器:是一个可以直接使用Lua语言的小程序。

  • 全局变量arg:编译器在运行代码前会通过预先定义的全局变量arg来获取解释器传入的参数。其中索引0中保存的内容为脚本名

  • 数值

  • 闭包:在Lua中函数可以被保存到变量(全局或局部)中,也可以作为某个参数传递给其他函数,也可以作为函数返回值——“第一类值”;Lua中函数可以访问包含其自身的外部函数中的变量——“词法定界”

一个闭包就是一个函数外加能够使该函数正确访问非局部变量所需的其他机制。借助闭包我们可以重定义一个函数,或者是重新封装,构建一个沙盒。

  • 编译:loadfile,从文件中加载Lua代码段,编译代码,将编译后的代码段作为一个函数返回

注意:解释型语言的区分并不在于源码是否被编译,而在于是否有能力(且轻易地)执行动态生成的代码。

  • 模块:创建模块的方式,一种是创建一个表并将所有需要导出的函数放入其中,最后返回这个表。另一种是把所有函数定义为局部变量,然后在最后构造返回的表。

  • 元表和元方法

  • 面向对象:参考基于原型的语言中的一些做法在lua中模拟类。我们只需创建一个专门被用以其他对象(类的实例)的原型对象即可。类和原型都是一种组织多个对象间共享行为的方式。

  • 垃圾回收:标记—清除机制。C 和 Lua 通过一个栈来进行交互,而且栈是属于Lua状态的一部分,所有垃圾收集器是知道C语言正在使用哪些值的。

  • Lua解释器: 一个可执行Lua的可执行文件,是一个小应用,它是由Lua标准库实现的独立解释器。这个解释器负责与用户的交互,将用户的文件和字符串传递给Lua标准库,由标准库完成主要的工作(例如,真正地运行代码)

  • 在Lua中调用C语言:我们必须以一种恰当的方式为Lua提供该C函数的地址,也就是要注册该函数。Lua调用C函数时,也使用了一个与C语言调用Lua函数时相同类型的栈,C函数从栈中获取参数,并将结果压入栈。

  • 用户数据(userdata):Lua中提供的可以用来存储任何数据的原始内存区域。

  • Lua状态:在支持多线程的系统中,一种有趣的设计是为每个线程创建一个独立的Lua状态。这种设计使得线程类似于POSIX进程,它实现了非共享内存的并发。

Lua复习总结

1.Lua中深拷贝和浅拷贝的区别?如何实现深拷贝

深拷贝就是开辟了一块新的内存,内存中存的是复制后的值
浅拷贝就是创建了一个指针,指向了共同的内存

浅拷贝只是简单的赋值,对新表的修改会影响原始的表;
深拷贝就是完全复制一份全新的表出来,和原始的表之间互不影响。实现方式:迭代遍历要复制的表的所有元素,最后还要拷贝元表(就是讲原来表的元表设置为新表的元表)。

拷贝:指的是用已经存在的对象创建出一个新的对象。从本质上讲,对象也是一份数据,因为它会占用内存。
创建对象:严格来说,包括两个阶段,首先要分配内存空间,然后再进行初始化。拷贝是在初始化阶段进行的,也就是用其他对象的数据来初始化新对象的内存。
浅拷贝:对于基本类型的数据以及简单的对象,他们之间的拷贝非常简单,就是按位复制内存,这种默认的拷贝行为就是浅拷贝。
深拷贝:当类持有其他资源,如动态分配的内存,指向其他数据的指针等,默认的拷贝构造函数就不能拷贝这些资源了,我们必须显示地定义拷贝构造函数,以完整地拷贝对象的所有数据。这种将对象所持有的其他资源一并拷贝的行为叫做深拷贝,我们必须显示地定义拷贝构造函数才能达到深拷贝的目的。不进行深拷贝的话,拷贝出来的对象如果包含指针的话会和原对象指针指向同一块内存,这样互相之间就会相互影响 ,这时就需要把原对象指针指向的那块内存也拷贝一份,新对象的指针指向新的内存。

C# 深拷贝:为什么要用到深拷贝?比如我们建了某个类Person,并且实例化出一个对象,然后,我们需要把这个对象复制一遍,并且复制出来的对象要跟之前的一模一样,我们一般会如何处理呢?

public class CopyTest
{
    public static void CopyPerson()
    {
        Person p = new Person();
        p.Name = "wang";
        p.Num = 19;
        Person p2 = p;
        p2.Name = "jun";
        p2.Num = 29;
        System.Console.WriteLine(p.Name + "," + p.Num.ToString());
        System.Console.WriteLine(p2.Name + "," + p2.Num.ToString());
    }
}

class Person
{
    public string? Name { get; set; }
    public int Num { get; set; }
}

在这里插入图片描述
运行后发现,新复制的对象的修改影响到了原对象。这里的原理是因为"=",在对引用类型使用时,仅仅是新建了一个新的引用变量,然后把引用地址复制给了新的引用变量而已,并没有复制真正地内容,这时候如果需要复制真正内容的话,就需要用到深拷贝的方式了。具体实现可以考虑反射和序列化。

    public static T DeepCopy<T>(T obj)
    {
        if (obj == null)
        {
            return obj;
        }
        
        var type = obj.GetType();

        if (obj is string || type.IsValueType)
        {
            return obj;
        }

        var retVal = Activator.CreateInstance(type);
        FieldInfo[] fieldInfos = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
        foreach (var field in fieldInfos)
        {
            try
            {
                field.SetValue(retVal, DeepCopy(field.GetValue(obj)));
            }
            catch (System.Exception)
            {

                // throw;
            }

        }
        
        return (T)retVal;
    }


    public static T DeepCopyByXml<T>(T obj)
    {
        if (obj == null)
        {
            return obj;
        }

        object retVal;
        using (MemoryStream ms = new MemoryStream())
        {
            XmlSerializer  bf = new XmlSerializer (typeof(T));
            bf.Serialize(ms, obj);
            ms.Seek(0, SeekOrigin.Begin);
            retVal = bf.Deserialize(ms);
            ms.Close();
        }

        return (T)retVal;
    }

回到Lua中,深拷贝的实现方式,遍历要拷贝的表,最后不要忘了原表也要拷贝

local a = {}
a.x = 1
a.b = {}
a.b.c = 2

function deepCopy(originObj)
    local _copy 
    function _copy(obj)
        if type(obj) ~= "table" then
            return obj
        end

        local newTable = {}
        for key, value in pairs(obj) do
            newTable[_copy(key)] = _copy(value)
        end
        return setmetatable(newTable, getmetatable(obj))
    end

    return _copy(originObj)
end

local m =deepCopy(a)
m.b.c =3 
print(a.b.c)

2.lua中ipairs和pairs的区别?
对于复杂的表,ipairs 是顺序遍历,遇到nil会停止,pairs是随机遍历,能遍历整个表。

3.lua中的userdata是什么?有什么作用?
是名为用户数据的基本类型。比如C语言和Lua交互的时候,在lua中可以用userdata 表示C中的任意类型数据,作用是提供了用来存储任何数据的原始内存区域。

4.解释下Lua中的元表和元方法。
假设要对两个表进行加法操作,会先检查是否有元表,且该元表里是否有元方法(_add),如果有的话就可以调用函数计算表的和。

5.说说lua中如何实现面向对象?
封装:可以用两张表来表示一个对象,一个用来保存对象的状态,一个用来保存对象的操作,从而实现私有性。
继承:通过设置元表就可以实现继承,通过设置元表,使用__index元方法让新的对象继承操作,也就相当于实现了共用对象的属性和行为。
多态:重写方法

6.Lua与C交互原理
使用虚拟栈进行交互,当C需要从Lua中获取一个值,只需调用Lua(C通过CAPI调用lua),lua就会将指定的值压入栈。
Lua调用C中函数,需要提前注册。

CAPI包括读写Lua全局变量的函数、调用Lua函数的函数、运行Lua代码段的函数,以及注册C函数(以便后续可被Lua代码调用)的函数。

C#与Lua交互原理:
C#调Lua:C#调用CAPI,通过CAPI调用Lua,然后是通过虚拟栈的形式进行,C#把请求或数据压入栈顶,Lua取出,处理后在压入栈,C#再从栈顶取出结果
Lua调C#:C#生成中间文件,通过CAPI注册到Lua虚拟机,然后lua就可以调用C#了

理解Lua的闭包机制

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/41607.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

轮播图,用vue来写一个简单的轮播图

轮播图&#xff0c;用vue来写一个简单的轮播图 写的很简单&#xff0c;就是一个小练习&#xff0c;哈哈哈&#xff0c;下面的几张图分别是轮播图的第一张&#xff0c;中间图&#xff0c;最后一张的效果图。 使用了vue 中的属性绑定 v-bind ,v-show 以及 事件监听 v-on 指令。 思…

pycharm新建分支并提送至GitHub

文章目录 前言pycharm创建本地分支Push至远程分支 前言 当我们写的项目代码越来越多时&#xff0c;一个master分支无法满足需求了&#xff0c;这个时候就需要创建分支来管理代码。 创建分支可以快速的回滚到某个节点的版本&#xff0c;也可以多个开发者同时开发一个项目&#…

xml.etree.ElementTree

python使用 xml.etree.ElementTree包的时候&#xff0c;对xml中的空标签进行了简写&#xff0c;想恢复成正常模式怎么弄

高并发的哲学原理(九)-- 细数四代分布式数据库并拆解

高并发的哲学原理&#xff08;九&#xff09;-- 细数四代分布式数据库并拆解 TiDB 和 OceanBase&#xff08;主从、中间件、KV、计算与存储分离、列存储、CAP定理&#xff09; 本文大约 15000 字&#xff0c;阅读需要 50 分钟。 上一篇文章啃硬骨头差点把我牙给崩了&#xff0c…

自动收小麦机(牛客2023萌新)

题目链接 示例1 输入 复制 4 1 2 1 1 4 5 2 2 2 3 4 输出 复制 10 说明 在第4格放出水流后&#xff0c;水流会流向第3格&#xff0c;由于第3格高度比第4格低&#xff0c;所以水流继续向左流向第2格&#xff0c;因为平地水流只能流2格&#xff0c;所以到达第2格后水流停…

GUI-Menu菜单实例

运行代码&#xff1a; //GUI-Menu菜单实例 #include"std_lib_facilities.h" #include"GUI/Simple_window.h" #include"GUI/GUI.h" #include"GUI/Graph.h" #include"GUI/Point.h"struct Lines_window :Window {Lines_window…

Nginx基础(复习理论篇)

一、Nginx基本概念 1、Nginx是什么 Nginx是一个高性能的Http和反向代理服务器&#xff0c;其特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上Nginx的并发能力确实在同类型的网页服务器中表现较好。 Nginx专为性能优化而开发&#xff0c;性能是其最重要的考量&…

数字原生时代,奥哲如何让企业都成为“原住民”?

22年前&#xff0c;美国教育学家马克‧普伦斯基&#xff08;Marc Prensky&#xff09;出版了《数字原生与数字移民》&#xff08;Digital Natives, Digital Immigrants&#xff09;一书&#xff0c;首次提出了“数字原住民”和“数字移民”两大概念&#xff0c;用来定义跨时代的…

SPEC CPU 2006 在 CentOS 5.0 x86_64 古老系统测试【4】-O3 不支持 编译失败

gcc -O3 编译失败 结论&#xff1a;默认情况下SPEC CPU 2006 1.2 不支持 gcc -O3编译参数。

【PostgreSQL内核学习(二)—— 查询分析】

查询分析 查询处理查询分析查询处理与查询分析的关系查询分析执行流程Lex和YaccLex&#xff1a;Yacc&#xff1a;词法分析工具Lex语法分析工具Yacc使用Lex和Yacc的案例 词法和语法分析以SELECT语句为例讲解 PostgreSQL中查询语句如何被解析并生成分析树。 语义分析 声明&#x…

Burp Suite---渗透测试工具

文章目录 Burp SuiteBurp Suite入门设置代理HTTP的代理 Proxy&#xff08;代理&#xff09; Burp Suite 是一款集成化的渗透测试工具&#xff0c;包含了很多功能&#xff0c;可以帮助我们高效地完成对Web应用程序的渗透测试和攻击。 Burp Suite由Java语言编写&#xff0c;基于…

Spring Security OAuth 2.0

1 概念 OAuth 2.0 到底是什么呢&#xff1f;我们先从字面上来分析下。OAuth 2.0 一词中的字母 “O” 是 Open 的简称&#xff0c;表示 “开放” &#xff0c; “Auth” 表示 “授权”&#xff0c;连在一起就表示 “开放授权”。 OAuth 2.0是一种授权框架&#xff0c;提供了一…

微服务架构Ribbon与OpenFeign的使用 【快速入门】

一、实现负载均衡&#x1f349; 1.什么是负载均衡&#x1f95d; 通俗的讲&#xff0c; 负载均衡就是将负载&#xff08;工作任务&#xff0c;访问请求&#xff09;进行分摊到多个操作单元&#xff08;服务器,组件&#xff09;上进行执行。 根据负载均衡发生位置的不同,一般分…

(Onenet)STM32L+BC20+MQTT协议传输温湿度,ADC,电压,GPS数据到Onenet物联网平台

1、材料准备 准备以下材料 2、设备连接 2.1 插入物联网卡 首先把BC20核心板从开发板上拆下来 然后将物联卡放置在BC20核心板内 物联卡放置完成将BC20核心板重新插入到开发板内&#xff08;注意不要弄错方向&#xff09; 同时接入天线 2.2 连接ST-Link仿真器 用3条杜邦线接…

SpringBoot使用Redis作为缓存器缓存数据的操作步骤以及避坑方案

1.非注解式实现 2.1使用之前要明确使用的业务场景 例如我们在登录时&#xff0c;可以让redis缓存验证码&#xff0c;又如在分类下显示菜品数据时&#xff0c;我们可以对分类和菜品进行缓存数据等等。 2.2导入Redis相关依赖 <dependency><groupId>org.springfra…

vue3 前端编码规范

prettier 配置 1. vscode 安装prettier 的 插件 2. 新建 .prettierrc 文件 {"semi": false, // 不尾随分号"singleQuote": true, // 使用单引号"trailingComma": "none" // 多行逗号分隔的语法&#xff0c;最后一行不加逗号 }eslin…

数据库应用:MySQL备份与恢复

目录 一、理论 1.数据备份 2.完全备份与恢复 3.完全备份与恢复应用 4.增量备份与恢复 5.增量备份与恢复应用 6.使用脚本备份 7.日志管理 二、实验 1.完全备份与恢复 2.增量备份与恢复 3.使用脚本备份 三、问题 1.mysqldump报错 四、总结 一、理论 1.数据备份 …

HDFS与MapResource笔记

客户端向NN请求上传文件 NN回应可以上传 请求上传块,返回DN 所以后面就比较慢 找最近的服务器进行 64K发到1节点,1节点立刻发给2节点,同时1节点自动开始落盘,这里,3个节点是同时落盘的. 因为缓存是在内存中,而持久化是将数据存到磁盘上. 副本节点选择: 1.安全:放不同机架 2.速…

销售易的12年与七个瞬间

导读&#xff1a;企业级没有捷径 12年对一家企业意味着什么&#xff1f; 在消费互联网领域&#xff0c;12年足够长&#xff0c;短短几年内上市的故事过去屡见不鲜。在企业服务的toB领域&#xff0c;产业成熟和企业发展的时间维度被拉长&#xff0c;但故事同样精彩。 2023年7月1…

flask实现get和post请求

1、实现get请求 在项目根目录创建app.py 代码如下&#xff1a; from flask import Flask,render_template,requestapp Flask(__name__)app.route("/regist/user/", methods[GET]) def regist():return render_template("regist.html") #默认去templat…