Lua语法总结

来源:互联网 发布:2017优化设计政治答案 编辑:程序博客网 时间:2024/06/10 12:24

基础


  • Lua区分大小写。
  • 注释格式
    -- 行注释    --[[        exp    --]]
  • 局部变量local, 其他的为全局变量,变量默认值为nil。
  • 只有false和nil为假。
  • Lua中字符串是不可变的常量。
  • “ .. ”是字符串连接操作符。
  • Lua没有整形,都是实数。
  • 在字符串前放置操作符”#”来获取字符串长度,某些情况下对table也适用。
  • 关系操作符: < > == ~= >= <=
  • and, or, not逻辑操作符返回的不一定是true和false,这点与C++不同,它返回的是对应表达式的运行结果。
  • 多重赋值
    a,b,c = 0,1 -- a为0, b为1, c为nil
  • 控制结构
    if exp then    elseif exp then    else    end
    while <exp is true> do    end
    repeat    until <exp is true>
    for var=exp1, exp2, exp3 do    end
    for i,v in ipairs(a) do    end
    for i in pairs(a) do    end




函数


函数也是值。

1. 多重返回值

  • 函数作为单独的语句时,会丢弃所有返回值。
  • 函数作为表达式的一部分时,只保留第一个返回值。
  • 在多重赋值中,函数作为最后一个表达式时,会保留尽可能多的返回值。
  • 将函数调用放在一对括号中,会迫使其只返回一个值。

2. 变长参数

function add(...)    local ret = 0    for i,v in ipairs({...}) do -- 或 for i,v in ipairs{...} do        ret = ret + v    end    return retendprint(add(1,2,9))
function foo(...)    local a,b,c = ...end 
-- 跟踪函数foo的调用function FooCallLog(...)    print("Call foo:", ...)    return foo(...)end
-- 使用函数select访问变长参数function add(...)  local ret = 0  for i = 1, select("#", ...) do -- select("#", ...)获取参数个数    local arg = select(i, ...) -- select(n, ...) 获取第n个参数    ret = ret + arg  end  return retendprint(add(1,3,5))

3. 闭合(Closure)函数

function newCounter() -- 该函数返回一个匿名函数    local i = 0    return  function () -- 在匿名函数内部,变量i是一个“非局部的变量”                i = i + 1                return i            endendc1 = newCounter()print(c1())  -- 输出:1print(c1())  -- 输出:2c2 = newCounter()print(c2())  -- 输出:1

4. 非全局函数

将一个函数存储到一个局部变量中,即得到了一个“局部函数”。

local lib={    foo = function(x,y) return x + y end,    goo = function(x,y) return x - y end}
local lib={}function lib.foo(x,y) return x + y endfunction lib.goo(x,y) return x - y end

对与递归程序等,为了防止局部函数为尚定义完毕,就要被编译,可以使用前置定义的方式。

local factfact = function(n)            if n == 0 then                 return 1            else                return fact(n-1)            end        end 




编译、执行与错误


1. loadstring

a = 20f = loadstring("local a = 10; print(a)")f() -- 输出:10

2. pcall

function foo(n)  if n > 0 then    print(n)  else    error("n need > 0")  endendif pcall(foo, -1) then  print("ok")else  print("error")end

pcall也可以执行匿名函数。



协同程序


Lua将所有和协同程序相关的函数存储在名为“coroutine”的table中。一个协同程序可以有4种状态:suspended, running, dead, normal。

co = coroutine.create(function()      coroutine.yield()      for i = 0, 2 do        if i == 2 then          error("oh No.")        end        print(i)      end    end  )print(coroutine.resume(co)) -- 当创建协同程序时,其处于suspended状态print(coroutine.resume(co)) -- resume是在保护模式中运行的print(coroutine.resume(co))--[[ 输出:true01false   D:\MyLua\Basic\coroutine.lua:5: oh No.false   cannot resume dead coroutine--]]




元表与元方法


Lua中每个值都有一个元表,table和userdata可以有各自独立的元表,而其他类型的值则共享其类型所属的单一元表。
Lua在创建新的table时不会创建元表。除了标准的字符串程序库外,其他的类型在默认情况下都没有元表。

t={}print(getmetatable(t))  -->nilprint(getmetatable("hi")) --> table: 0x80772e0print(getmetatable(10))  --> nil

可以在元表中定义的原方法(或字段)如下:
+ __add 加
+ __sub 减
+ __mul 乘
+ __div 除
+ __unm 相反数
+ __mod 取模
+ __pow 乘幂
+ __eq 等于
+ __lt 小于
+ __le 大于
+ __concat 连接
+ __tostring 字符串转化
+ __metatable 保护元表

local mt = {}mt.__tostring = function(t)  local l = {}  for e in pairs(t) do    l[#l + 1] = e  end  return "{" .. table.concat(l, ", ") .. "}"endages = {Jeff = 18, Jim = 19, Lucy = 20}print(ages)  --> table: 0x003286e8setmetatable(ages, mt)print(ages)  --> {Lucy, Jeff, Jim}mt.__metatable = "not your business"print(getmetatable(ages)) --> not your business
  • __index Table访问
  • __newindex Table更新
-- 跟踪Table访问的示例local index = {}local mt={  __index = function(t, k)    print(string.format("*access to element %s, value %s", k, t[index][k]))    return t[index][k]  end,  __newindex = function(t, k, v)    print("*update of element " .. tostring(k) .. "to " .. tostring(v))    t[index][k] = v  end}function track(t)  local proxy = {} -- __index和__newindex都是在table中没有所需访问的index时才发挥作用  proxy[index] = t -- 类似多维数组  setmetatable(proxy, mt)  return proxyendages = {Jeff = 18, Jim = 19, Lucy = 20}ages = track(ages)print(ages.Jeff)address = {Jeff = "WuHan", Jim = "Beijin", Lucy = "Taiyuan"}address = track(address);print(address.Jim)




模块与包


模块搜索

对于require(“foo”),Lua先在预定路径中搜索foo.lua,如果没有搜索就会搜索foo.DLL。
require用于搜索Lua文件的路径存放在变量package.path中,Lua启动后便以环境变量LUA_PATH的值来初始化该变量;
搜索DLL文件的路径存放在package.cpath中,同理,Lua启动后会用LUA_CPATH环境变量的值来初始化该变量。

print(package.path)--[[;.\?.lua;C:\Program Files (x86)\ZeroBrane\bin\lua\?.lua;--]]

require会用模块名来替换每个“?”,依次匹配搜索,直到搜索成功。

基本模块编写

编译一个模块最简单的方法就是:创建一个table,并将所有需要导出的函数放入其中,最后返回这个table。

-- file: basic_mod.luabasicmod = {}basicmod.name = "basic mod"function basicmod.func1()  print("func1")endreturn basicmod

调用该模块:

require("basic_mod")print(basicmod.name) --> basic modprint(basicmod.func1())  --> func1

但是上面的写法会导致模块中的每个函数或成员前面都带有该模块的名称,更改模块名称会牵一发而动全身,针对这个问题,可以进行如下改进:

-- file: basic_mod.lualocal M = {}  -- 借用一个局部table变量basicmod = MM.name = "basic mod"function M.func1()  print("func1")endreturn basicmod

实际上,可以完全避免写模块名,因为require会将模块名作为参数传递给模块:

-- file: basic_mod.lualocal modname = ...local M = {}_G[modname] = Mpackage.loaded[modname] = MM.name = "basic mod"function M.func1()  print("func1")end
require("basic_mod") -- 此时模块函数存储的table名称就是模块的文件名print(basic_mod.name)print(basic_mod.func1())

在Lua5.1中,提供了一个新的函数module,简化模块的编写:

module(..., package.seeall)name = "basic mod"function func1()  -- 函数前不需要加入模块名限定  print("func1")end




面向对象


self参数

使用this(或self)参数是所有面向对象语言的核心。大多数面向对象语言都能对程序员隐藏部分this参数,从而使得程序员不必显示的声明这个参数。
Lua只需要使用冒号就能隐藏该参数。
冒号的作用就是在一个方法的定义中添加一个额外的隐藏参数,以及在一个方法的调用中添加一个额外的实参,冒号只是一种语法便利,并没有引入任何新的东西。

Account = {balance = 0}function Account.cost(v)  Account.balance = Account.balance - v -- 只能针对全局名称Account来工作endAccount.cost(100) -- 调用正常a = Account; Account = nila.cost(100)    -- 错误:attempt to index global 'Account' (a nil value)

改进如下:

Account = {balance = 0}function Account.cost(self, v)  self.balance = self.balance - vendAccount.cost(Account, 100)a = Account; Account = nila.cost(a, 100)

使用冒号:

Account = {balance = 0}function Account:cost(v)  self.balance = self.balance - vendAccount:cost(100)a = Account; Account = nila:cost(100)
1 0
原创粉丝点击