Lua语法(二)——闭包/日期和时间

简介: Lua语法(二)——闭包/日期和时间

概述

关于闭包,模块和包的概念。
Lua中的闭包、模块和包都是用来组织和封装代码的机制。

闭包

闭包是指一个函数和其相关的环境变量的组合。当一个函数在其外部定义的环境中使用某些变量时,这些变量将会保存在闭包中,使得函数可以在其定义之外的地方继续使用这些变量。使用闭包可以实现很多高级的编程技巧,例如函数工厂、延迟计算等。

--闭包案例:url解码
str = "word=%22%E4%BD%A0%E5%A5%BD%22;name=%22%E5%BC%A0%E4%BC%9F%22"
function urldecode(s)
    s = string.gsub(s,"+"," ")
    s = string.gsub(s,"%%(%x%x)",function (h)
        return string.char(tonumber(h,16))
    end)
    return s
end

print(urldecode(str))
--输出    word="你好";name="张伟"

模块和包

Lua5.1以后,引入了模块和包

可以将其他lua文件作为模块,让当前lua文件调用

模块和包相关函数

dofile、loadfile和require 的区别

在Lua语言中,dofile、loadfile和require都是用于加载和执行Lua代码的函数,但它们之间有一些区别。

dofile函数是最简单的加载和执行Lua代码的方式。它接受一个文件路径作为参数,并返回执行结果。dofile函数会直接加载并执行指定路径的Lua脚本文件,返回脚本的执行结果。每次调用dofile函数都会重新加载和执行脚本文件。

loadfile函数用于加载Lua代码块并返回一个函数。它接受一个文件路径作为参数,并返回一个函数对象,该函数可以用于多次执行该代码块。loadfile函数只加载并编译脚本文件,不会立即执行代码。调用返回的函数对象可以多次执行代码块,每次执行返回执行结果。

require函数是用于加载和执行Lua模块的函数。它接受一个模块名作为参数,并返回模块的返回值。require函数先检查指定的模块是否已经加载,如果已经加载则直接返回模块的返回值。如果模块尚未加载,则会搜索Lua模块路径来查找并加载对应的Lua文件。require函数只会加载和执行模块一次,后续调用require函数会直接返回缓存的模块返回值。

需要注意的是,dofile和loadfile可以加载任意的Lua代码文件,而require函数则只能加载具有特定规范的Lua模块文件。

案例:

如果模块名和文件名不一致,那么需要将模块所在的文件放到Lua根目录下的lua文件夹里面

如果模块名和文件名一致,则可以将模块所在的文件和当前文件放在同一个文件夹下,所以,建议让模块名和文件名保持一致

例如模块名 叫 model ,那么文件名叫 model.lua为一致

否则模块会require调用失败

require
--model.lua
local model = {
   }

model.wwww = function ()
    print("test")
end

return model        --这里不要忘记return

--test.lua
local mod =require("model")    --可以自定义一个本地的名字

mod.wwww()
--输出    test
dofile

读取文件并直接运行

--block.lua
print("here is block")

local function block()
    print("bolck fun is doing")
end

return {
   fun=block}

--test.lua
local f = dofile("block.lua")
f.fun()

--输出
here is block
bolck fun is doing
loadfile

需要手动执行函数

--block.lua
print("here is block")

local function block()
    print("bolck fun is doing")
end

return {
   fun=block}

--test.lua
local f =loadfile("block.lua","bt")
if f then
    f()
    print("----------")
    f().fun()
end
--输出
here is block
----------
here is block
bolck fun is doing

模式匹配

模式串含义

--1.字符模式类型
.    任意字符
%c    控制字符
%s    空白字符
%g    除空格外的可打印字符
%d    十进制数字
%x    十六进制数字
%a    字母
%l    小写字母
%u    大写字母
%w    字母和数字
%p    标点符号

这些模式串的大写表示他们的补集,例如
%a代表字母,%A则代表非字母的字符

--2.魔法字符
主要有一下这些属于魔法字符,用于拓展上面的含义
() . % + - * ? [ ] ^ $
其中:
%用来转义,%% 表示匹配一个百分号,%?匹配一个问号
[] 表示字符需要符合中括号里面的匹配要求,例如[a-z]表示匹配字符需要属于a-z里面的一个;[01]表示匹配0或者1
[]()大多用来限制模式串的匹配范围

? 字符出现零次或一次
+ 字符重复一次或多次
* 字符重复零次或多次
- 字符重复零次或多次
详细可参考通用的模式匹配规则

string.find

查找某个字符串在第几个位置,从1开始

string.find("hello world","wor")    --输出  7  9  表示第7到第9个字符串
string.find("hello world","war")    --输出 nil

string.gsub

找到某个字符并替换为指定字符

或者找到某个匹配的模式,替换为指定字符

-- 查找 l 字符, 用 .  替代,输出替换后的字符串,并且输出替换的个数
string.gsub("hello world","l",".")    --输出 he..o wor.d    3
-- 查找 ll 字符,用 . 替代
string.gsub("hello world","ll","..")    --输出 he..o world    1
string.gsub("hello world","ll",".")        --输出 he.o world    1

str= "this 8is 5a line"
su = string.gsub(str,"%d","")
print(su)
--输出    this is a line

--url解码
str = "word=%22%E4%BD%A0%E5%A5%BD%22;name=%22%E5%BC%A0%E4%BC%9F%22"
function urldecode(s)
    s = string.gsub(s,"+"," ")
    s = string.gsub(s,"%%(%x%x)",function (h)
        return string.char(tonumber(h,16))
    end)
    return s
end

print(urldecode(str))
--输出    word="你好";name="张伟"

string.match

在目标字符串中进行模式串的搜索

str = "hello 09/09/1999"
m = string.match(str,"%d+/%d+/%d+")
print(m)
--输出    09/09/1999

string.gmatch

在目标字符串中进行模式串的搜索,找出所有的生成一个表,用来遍历

str= "this is a line"
word={
   }
for w in string.gmatch(str,"%a+") do
    word[#word+1] = w
end
for k,value in pairs(word) do
    print(value)
end
--输出
this
is
a
line

日期和时间

os.time

表示1970年1月1日0点0分0秒到当前的秒值,其他时区见下方代码

print(os.time())

--给它一个参数,表示计算当前年月日到1970.1.1  0点0分0秒的秒数
print(os.time({
   year=1970,month=1,day=1,hour=0,min=0,sec=0}))
--这一步有人发现os.time给参数报错了,原因是可能你不在国际时间的0时区
--如果你在东8区,那么起始的0值是
--1970.1.1  8点0分0秒
--也就是说你要修改参数为一下时间及之后才可以正确输出
print(os.time({
   year=1970,month=1,day=1,hour=8,min=0,sec=0}))
--输出    0

os.date

输出当前的日期,可以用指示符参数进行控制日期的输出格式

--1.常规用法
print(os.date())
--输出当前日期

--2.指示符简介
--2.1常用指示符
%Y    年份    例如1909
%y    年份简写    例如09
%m    月份
%d    日
%H    24小时制的小时
%I    12小时制的小时
%M    分钟
%S    秒
--2.2不常用指示符
%c 月日年和时间
%d    一个月中的第几天
%j    一年中的第几天
%w    星期几 数字表示
%W    一年中的第几周
%p    am或者pm
%a    星期几英文简写
%A    星期几英文全称
%b    月份英文简写
%B    月份英文全称

--3.基本使用方式
print(os.date("%Y-%m-%d"))
--输出当前时间

--4.指定秒值输出指定格式
t=os.time()
print(os.date("%Y-%m-%d",t))
print(t)

--上面形式的简写
print(os.date("%Y-%m-%d",os.time()))

os.difftime

用来计算两个秒值相差多少秒,如果前面的比后面的小,那么输出的是负数

t1 = os.time({
   year=1997,month=1,day=1,hour=8,min=0,sec=1})
t2 = os.time({
   year=1997,month=1,day=1,hour=8,min=0,sec=0})
print(os.difftime(t1,t2))
--输出    1.0

位运算

位运算符有

&(按位与) |(按位或) ~(按位异或) >>(逻辑右移) <<(逻辑左移)

print(string.format("%x",0xff<<8))
--等价于
print(string.format("%x",0xff>>-8))

编译、执行和错误处理

1.预编译

--block.lua
print("here is block")

打开文件位置,使用下面命令进行预编译
luac -o block.lc block.lua
--此时产生中间文件block.lc
--再执行
lua block.lc
--输出 here is block

2.错误处理

lua 中的 pcall 和 xpcall 是用来捕获和处理错误的函数。

pcall 函数的基本用法为:

function pcall(f, ...)
    -- 尝试执行函数 f,并将其参数传递给它
    -- 如果执行过程中没有发生错误,则返回 true 和函数的返回值
    -- 如果发生错误,则返回 false 和错误信息
end

xpcall 函数的基本用法为:

function xpcall(f, err_func, ...)
    -- 尝试执行函数 f,并将其参数传递给它
    -- 如果执行过程中没有发生错误,则返回 true 和函数的返回值
    -- 如果发生错误,则调用 err_func 函数处理错误,并返回 false 和处理后的结果
end

pcall 和 xpcall 函数的区别在于,xpcall 函数可以指定一个错误处理函数 err_func,在发生错误时调用该函数来处理错误。err_func 函数接受一个参数,即错误信息,并返回处理后的结果。

以下是 pcall 和 xpcall 的用法示例:

-- pcall 示例
local function getstr(str)
    if type(str)~="string" then
        error("it is not a string")
    end
    print(str)
end

local success, result = pcall(getstr, 10)
if success then
    print("Result:", result)
else
    print("Error:", result)
end
--输出
Error:    \test.lua:3: it is not a string

-- xpcall 示例
local function getstr(str)
    if type(str)~="string" then
        error("it is not a string")
    end
    print(str)
end

local function handle_error(err)
    print("Error:".."print in handle", err)
    return 0
end

local success, result = xpcall(getstr, handle_error, 10)
print("Result:", result)
--输出
Error:print in handle  \test.lua:3: it is not a string
Result:    0

在以上示例中,当调用 divide 函数时,如果除数为0,则会抛出一个错误。通过使用 pcall 函数,在调用 divide 函数时捕获错误,并根据返回值来判断是否发生了错误。

而在使用 xpcall 函数时,除了能够捕获错误外,还可以指定一个错误处理函数 handle_error 来处理错误。在错误发生时,会调用 handle_error 函数,并将错误信息作为参数传递给它。在 handle_error 函数中,可以根据需要进行错误处理,并返回一个处理后的结果。

目录
相关文章
|
3月前
|
Java API C语言
Lua语法(一)
Lua语法(一)
40 0
Lua语法(一)
|
3月前
Lua语法(六)——面相对象编程
Lua语法(六)——面相对象编程
33 0
|
3月前
|
Java
Lua语法(五)——垃圾回收
Lua语法(五)——垃圾回收
87 0
|
3月前
Lua语法(四)——协程
Lua语法(四)——协程
42 0
|
3月前
|
索引
Lua语法(三)——元表与元方法
Lua语法(三)——元表与元方法
41 0
|
5月前
|
存储 缓存 NoSQL
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
82 1
|
6月前
|
NoSQL JavaScript Java
Lua开发环境搭建和基础语法
Lua开发环境搭建和基础语法
139 1
|
6月前
|
Java Kotlin 索引
Lua 起航 —— 一些常用基础语法
Lua 起航 —— 一些常用基础语法
71 1
|
6月前
|
消息中间件 自然语言处理 Kubernetes
Lua闭包和Upvalue上值
Lua闭包和Upvalue上值
|
存储
Lua基本语法
Lua基本语法