Lua 学习之基础篇十<Lua 常见的语法规则>

下面讲一些lua 常见的用法和规则,可以为学习理解lua带来帮助。

1. if判断

lua把 nil 和false 视为“假”,其他都为“真”

2. 逻辑运算符 and or

lua的and or 可以用来构成三元表达式,如下:

> = 1 == 1 and 1 or 2
1

但如果是这样写,就不是你想要的结果了:

> = 1 == 1 and false or true
true

这是因为,and 运算符判定 false不成立,就继续执行了 or 运算符的结果(nil和false lua都认为为假)
如果你一定要返回 true 或 false,要这么写:

> = ( 1 == 1 and {false} or {true} )[1]
false

3. local变量声明

local var1=1,var2
以上 ,var1和var2的作用域不同,var1是所在作用域的变量,var2可能是全局变量。实际上述命令解释后为 var1 取 "1,var2" 组成的值第一个值,类似 local var1 = ...
请注意变量的声明,如果不确定,就老老实实依依赋值。

local var1
local var2=1
print(var1)  --nil
print(var2)  --1
print("=====")
local var3 =1,var4
print(var3) --1
print(var4) --nil
print("=====")
local  var5, var6=1
print(var5) --1    ->是不是很奇怪-  -、这里的var5竟然是1
print(var6) --nil

4. table是否为空

if a == {} then

结果是false,这是一个逻辑错误,实际比较table a的内存地址和一个匿名table的是否相同

正确的写法是:

if next(a) == nil then

5. 多个变量赋值

name,name = 1,2

那name等于多少呢?

实际上name值为1,可以写个小例子 a,b = 2,3,4打印就可以看到了。a=2,b=3

6. table的key规则

t[name]与t["name"], t.name

第一种和后两种是不同的,第一种会根据取name的值做key,后两种以 "name"做key。这种情况还有:
t = {[name] = 1}

t = {name = 1}
t = {["name"] = 1}

7. table的长度

取得 table 长度最常用的做法是 #table,如下:

> t = {1,2,3}
> #t
3

但 # 操作符也是有局限的,不支援数组以外的对象计算,所以要谨记

> t = { 10, n = 20, 30, 40 }
> #t
3 --长度是4,所以,要采用其他方式判定长度

另外,通过把元素设 nil 无法改变 #table 的结果(除非是数组最后一个元素);而 table.remove 则可以立即更新 #table 的结果

t ={1,2,3}
t[1]=nil
print(#t) --3

table.remove(t,1)
print(#t) --2

8. table引用问题

将一个table复制给另外一个table,修改这个新的table值会影响原来的table,但通过clone可以改变这一行为

function deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[deepcopy(orig_key)] = deepcopy(orig_value)
        end
        setmetatable(copy, deepcopy(getmetatable(orig)))
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end

9. 函数返回值

function f123()
    return 1, 2, 3
 end
function f456()
     return 4, 5, 6
 end
 print(f123())  --1 2 3
 print(f456())  --4 5 6

 print(f123(), f456()) -- 1 4 5 6
 print(f456(),1) --4 1

如果函数不是处于列的最后一个,只返回一个值

10.浮点数问题

这是浮点数都会有的精度丢失问题,lua也有这个问题。再看下整数与浮点数的比较

> =10==10.00000000000000000
true
> =10==10.00000000000000001
true
> =10==10.00000000000000000
true
> =10==9.999999999999999999
true

所以,这边测试了一下,lua 的浮点数会精确到15位,所以在比较精确的比较之前确认好精度在进行比较

11. 冒号语法

冒号语法可以用来定义函数, 这样的话,函数会有一个隐式的形参 self。

写法如下:
? function t:f (params) body end
冒号语法实际上是一种语法糖,等效于:
? t.f = function (self, params) body end

local t={a=123}

function t.f1(self, p)
    print(self.a, p) --self.a 访问t中a的值
end

function t:f2(p)
    print(self.a, p)
end

t:f1(1)
t.f1(t,1)
t:f2(1)
t.f2(t,1)

以上几个结果都是 123 1
这里,通过冒号方式调用函数不需要加入self参数,而点号则需要。

12. 函数闭包

当一个函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部变量,这种特征我们称作词法定界。

function fn()
    local i = 0
    return function()     -- 注意这里是返回函数的地址,不是执行
       i = i + 1
        return i
    end
end

c1 = fn()           -- 接收函数返回的地址
print(c1())  --> 1          --c1()才表示执行 ,i 此时为0
print(c1())  --> 2          --继续执行函数体 此时i =1上次执行的结果

如上,调用c1()时,fn函数明显已经返回,lua闭包闭包思想正确处理这种情况:

  • 我们称i为从c1的外部局部变量(external local variable)或者upvalue。
  • 简单的说,闭包是一个函数以及它的upvalues

如果我们再次调用fn,将创建一个新的局部变量i:

c2 = fn()
print(c2())  --> 1
print(c1())  --> 3
print(c2())  --> 2

13. 函数尾调用

  • 尾调用是一种类似在函数结尾的goto调用。
  • 当函数最后一个动作是调用另外一个函数时,我们称这种调用尾调用。
function f(x)
    return g(x)  -- 类似于goto g(x)函数的地址
end
  • 尾调用不需要使用栈空间,因此尾调用递归的层次可以无限制的。

例如下面调用不论n为何值不会导致栈溢出。

function foo (n)
    if n > 0 then return foo(n - 1) end
end

需要注意的是:必须明确什么是尾调用。
一些调用者函数调用其他函数后也没有做其他的事情但不属于尾调用。比如:

function f (x)
    g(x)
    return
end

上面这个例子中f在调用g后,不得不丢弃g地返回值,所以不是尾调用,同样的下面几个例子也不时尾调用:

return g(x) + 1      -- 还需+1
return x or g(x)     -- 还需比较
return (g(x))        -- 还需调整为一个返回值

原文地址:https://www.cnblogs.com/xiaoqiangink/p/12083006.html

时间: 2024-10-09 18:17:56

Lua 学习之基础篇十<Lua 常见的语法规则>的相关文章

Lua 学习之基础篇七&lt;Lua Module,Package介绍&gt;

Lua 之Module介绍 包管理库提供了从 Lua 中加载模块的基础库. 只有一个导出函数直接放在全局环境中: [require]. 所有其它的部分都导出在表 package 中. require (modname) 加载一个模块. 这个函数首先查找 [package.loaded] 表, 检测 modname 是否被加载过. 如果被加载过,require 返回 package.loaded[modname] 中保存的值. 否则,它会为模块寻找加载器. require 遵循 [package.

Lua 学习之基础篇五&lt;Lua 之 OS 库&gt;

lua os库提供了简单的跟操作系统有关的功能 1.os.clock() 返回程序所运行使用的时间 local nowTime = os.clock() print("now time is ",nowTime) local s = 0 for i = 1,100000000 do s =s+i end spendTime = os.clock() - nowTime print(string.format("Spend time is : %.2f\n", spe

Lua 学习之基础篇六&lt;Lua 之IO 库&gt;

引言 I/O 库提供了两套不同风格的文件处理接口. 第一种风格使用隐式的文件句柄: 它提供设置默认输入文件及默认输出文件的操作, 所有的输入输出操作都针对这些默认文件. 第二种风格使用显式的文件句柄. 当使用隐式文件句柄时, 所有的操作都由表 io 提供. 若使用显式文件句柄, io.open 会返回一个文件句柄,且所有的操作都由该文件句柄的方法来提供. 表 io 中也提供了三个 和 C 中含义相同的预定义文件句柄: io.stdin io.stdout io.stderr. I/O 库永远不会

Lua 学习之基础篇九&lt;Lua 协同程序(Coroutine)&gt;

引言 讲到协程,首先来介绍一下线程和协程的区别 lua协程和多线程 相同之处:拥有自己独立的桟.局部变量和PC计数器,同时又与其他协程共享全局变量和其他大部分东西 不同之处:一个多线程程序可以同时运行几个线程(并发执行.抢占),而协程却需要彼此协作地运行,并非真正的多线程,即一个多协程程序在同一时间只能运行一个协程,并且正在执行的协程只会在其显式地要求挂起(suspend)时,它的执行才会暂停(无抢占.无并发). 注意: Lua中的协程无法在外部将其停止,有可能导致程序阻塞 运行的是主线程时调用

Lua 学习之基础篇八&lt;Lua 元表(Metatabble)&amp;&amp;继承&gt;

讲到元表,先看一段table的合并动作. t1 = {1,2} t2 = {3,4} t3 = t1 + t2 attempt to perform arithmetic on a table value (global 't1') 程序会报错,因为不知道如何对两个table执行+运算,这个时候就需要通过元表来定义,有点类似c中的运算符加载.我们看一下如何通过元表实现合并操作. local mt = {} --定义mt.__add元方法(其实就是元表中一个特殊的索引值)为将两个表的元素合并后返回

一步步学习javascript基础篇(3):Object、Function等引用类型

我们在<一步步学习javascript基础篇(1):基本概念>中简单的介绍了五种基本数据类型Undefined.Null.Boolean.Number和String.今天我们主要介绍下复杂数据类型(即引用数据类型) Object类型 我们用的最多的引用类型就属object类型了,一般用来存储和传输数据是再好不过的.然,它的两种创建方式我们是否了解呢? 1.通过构造函数来创建 如: var obj = new Object(); 在js中的引用类型有个非常灵活的用法,可以动态的附加属性和赋值.

渗透学习笔记--基础篇--sql注入(字符型)

环境:dvwa1.7数据库:mysql前置知识:sql语句(Click me)      在进行sql注入前,我们先熟悉熟悉select语句.一.打开我们的sql终端 二.进入之后可以看到有mysql>我们输入sql语句,即可返回我们想要的结果,注意分号哟!我们使用的dvwa,在我们前几章设置的时候,会在数据库中生成一个dvwa的database:这里我们使用它来进行我们的select 语句:(1)使用dvwa数据库use dvwa;(2)在users表里查询用户名为'admin'的所有信息se

iOS开发学习笔记:基础篇

iOS开发需要一台Mac电脑.Xcode以及iOS SDK.因为苹果设备都具有自己封闭的环境,所以iOS程序的开发必须在Mac设备上完成(当然,黑苹果应该也是可以的,但就需要花很多的精力去折腾基础环境),Xcode是一个集成开发环境,包括了编辑器.调试.模拟器等等一系列方便开发和部署的工具,iOS SDK则是开发应用所必需,不同的SDK分别对应不同的iOS版本或设备,通常我们需要下载多个iOS SDK以确保我们开发的程序能够在不同版本的iOS上正常运行. 创建新工程 Xcode提供了很多种工程模

Python学习笔记基础篇——总览

Python初识与简介[开篇] Python学习笔记——基础篇[第一周]——变量与赋值.用户交互.条件判断.循环控制.数据类型.文本操作 Python学习笔记——基础篇[第二周]——解释器.字符串.列表.字典.主文件判断.对象 Python学习笔记——基础篇1[第三周]——set集合 Python学习笔记——基础篇2[第三周]——计数器.有序字典.元组.单(双)向队列.深浅拷贝.函数.装饰器 Python学习笔记——基础篇[第四周]——迭代器&生成器.装饰器.递归.算法.正则表达式 Python