Lua - 语言学习笔记
来源:互联网 发布:js弹出窗口 编辑:程序博客网 时间:2024/05/29 12:32
看云风的Skynet的时候, 对Lua生出了很大的兴趣,抽出时间看了下Lua在线手册,特作此记录。
本文仅为Lua语言作为独立的脚本语言的部分知识速记。 虽然Lua被设计来作为宿主语言的嵌入脚本,不过简单的逻辑纯Lua也可以实现。
关键字和操作符
关键字
and break do else elseifend false for function ifin local nil not orrepeat return then true until while
这些关键字包含了 :
- 类型(值)关键字
nil true false function
- 控制流关键字
do while
,repeat until
,if then else elseif
,for in
, 和end break return
。 - 逻辑运算关键字
and or not
。 - 作用域关键字
local
。 - 以下常规关键字没有提供 :
continue
。main
。
操作符
+ - * / % ^ # == ~= <= >= < > = ( ) { } [ ] ; : , . .. ...
- 不等于是
~=
而不是!=
。 - 没有逻辑运算符
&& || !
, 使用对应关键字 。 ..
表示字符串连接。#
运算符表示计算大小(长度)!
table = {'a' , 'b' ,[4]= '4', aa='bb'}str = "12345"print(#table)print(#str)
输出
-- 从索引1开始顺序计数,直到数字索引中断。并不代表table的真正大小,仅代表```ipairs``` 接口的返回pair数。2-- 计数字符串中字符个数 \0 不计数。5
类型
- nil
- 即是类型有事值 。
- 在判断中表示
false
- boolean
nil 、 false
表示false
。- 其余全部表示
true
包括0
和字符'\0'
。
- number
- 默认双精度
- 可以通过 luaconf.h 文件修改 (重新编译Lua解释器)。
- string
- 没有字符的概念,全部是字符串。
- 可以使用
' '
," "
或者[=*[ ]=*]
。 \0
结尾 。
- function
- function也是变量类型
- 支持闭包。
- userdata
- 表示 C (宿主) 数据 , 仅宿主代码可以创建或者修改 。
- 利用元表(
metatable
)为它指定操作函数。
- thread
- 协程类型,基于单线程,需要手动切入切出。
- table
- 默认索引是数字,从
1
开始 。 ( 数字 0 索引是可用的, 只是默认索引不会去不使用 ipairs 函数也不会去检测 数字 0) - 索引可以是除去
nil
之外的所有类型 。 - 一个table不必使用统一类型的索引。
- 值可以是除去
nil
之外的所有类型,a[i] = nil
意味着删除a[i]
。 - 语法糖
a[b]
等价于a.b
。a={["test"]=1}
等价于a= {test=1}
。
- 默认索引是数字,从
Table 的测试代码
-- Construct a tabletable_a = {'test';["x"] = 111 ; 'Woo',y='xx', [0] = 'test 0 number'}table_a[3]='2 set'table_a[5]='5 set'table_a['\0']='test 0 again'table_a['0']='test 0 character'-- Tarvel through a table's first part integer pairsfor i , v in ipairs(table_a) do print(i,v);end-- Tarvel through a table's all pairsfor i , v in pairs(table_a) do print(i,v);end
输出 :
-- ipair 循环输出 :1 test2 Woo3 2 set-- pair 循环输出 : 1 test2 Woo3 2 set5 5 sety xxx 1110 test 0 again character -- 字符 0 test 0 again -- \0 字符不显示0 test 0 number -- 数字 0
(CSDN-BUG)
语句
分号
lua的语句总是可以使用分号结尾, 但是在没有歧义的情况下也可以不使用。 条件判断的括号也是可有可无 。
判断
if condition then elseif ( condition ) thenelseend
循环
while
while condition do...end
repeat until
-- 其实这个就是C里面的 do ... while 循环repeat ...until condition
for
-- 给var一个初始值, 一个终止值 和一个步长, 循环之。-- 步长可以省略 , 省略则为1。for var = 1 , 10 , 2 do ...end
for in
-- Lua的 foreach 循环a_table = { 1, 12, 3}for i , v in pairs(a_table)do ...end
(CSDN-BUG)
函数
函数定义
普通函数
-- 直接定义function foo ( param1 ) -- like print(param1)...end-- 赋值定义给某个变量foo = function ( param1 ) ...end
添加到某个table / userdata 的metatable中
-- 定义给特定变量-- 方法1 : 仅仅绑定方法test={}test.op = function(param1)...end-- 然后如下使用 test.op('param')-- 方法2 :绑定且默认传入 “:” 前的变量为第一个参数,参数名字是self 。test={test1=1 , test2=2}test:op = function(param1) -- 使用 : 而不是 . -- 已经默认传入test 作为self参数 , 直接如下使用print(self.test1 , self.test2)...end-- 然后如下使用这个函数。test:op('param') -- 使用 : 而不是 .
函数闭包
function newCounter() local i = 0 return function() -- anonymous function who hold i variable i = i + 1 return i endendc1 = newCounter()print(c1()) --> 1 print(c1()) --> 2
支持多返回值
参见
http://book.luaer.cn/_37.htm
(CSDN-BUG)
metatable
定义
Lua 中的每个值都可以用一个 metatable。 这个 metatable 就是一个原始的 Lua table , 它用来定义原始值在特定操作下的行为。 你可以通过在 metatable 中的特定域设一些值来改变拥有这个 metatable 的值 的指定操作之行为。 举例来说,当一个非数字的值作加法操作的时候, Lua 会检查它的 metatable 中 “__add” 域中的是否有一个函数。 如果有这么一个函数的话,Lua 调用这个函数来执行一次加法。
我们叫 metatable 中的键名为 事件 (event) ,把其中的值叫作 元方法 (metamethod)。 在上个例子中,事件是 “add” 而元方法就是那个执行加法操作的函数。
你可以通过 getmetatable 函数来查询到任何一个值的 metatable。
你可以通过 setmetatable 函数来替换掉 table 的 metatable 。 你不能从 Lua 中改变其它任何类型的值的 metatable (使用 debug 库例外); 要这样做的话必须使用 C API 。
每个 table 和 userdata 拥有独立的 metatable (当然多个 table 和 userdata 可以共享一个相同的表作它们的 metatable); 其它所有类型的值,每种类型都分别共享唯一的一个 metatable。 因此,所有的数字一起只有一个 metatable ,所有的字符串也是,等等。
__add(a, b) --对应表达式 a + b__sub(a, b) --对应表达式 a - b__mul(a, b) --对应表达式 a * b__div(a, b) --对应表达式 a / b__mod(a, b) --对应表达式 a % b__pow(a, b) --对应表达式 a ^ b__unm(a) --对应表达式 -a__concat(a, b) --对应表达式 a .. b__len(a) --对应表达式 #a__eq(a, b) --对应表达式 a == b__lt(a, b) --对应表达式 a < b__le(a, b) --对应表达式 a <= b__index(a, b) --对应表达式 a.b__newindex(a, b, c) --对应表达式 a.b = c__call(a, ...) --对应表达式 a(...)
实例
重载 + 运算符
-- Create 2 table with same structfraction_a = {numerator=2, denominator=3}fraction_b = {numerator=4, denominator=7}-- Create a metatable fraction_op={}function fraction_op.__add(f1, f2) ret = {} ret.numerator = f1.numerator * f2.denominator + f2.numerator * f1.denominator ret.denominator = f1.denominator * f2.denominator return ret;end-- set metatable to tablesetmetatable(fraction_a, fraction_op)setmetatable(fraction_b, fraction_op)-- call __add operator fraction_s = fraction_a + fraction_b;print(fraction_s.numerator,fraction_s.denominator)
利用metatable实现面向对象编程
-- 实现简单的继承Father={ name = '1 Father'};function Father:Print() print('I am '..self.name);endSon={};setmetatable(Son,{__index=Father});-- Print I am 1 Father if Son.Print was not defined.Son:Print();--实现new接口Person={}function Person:new(p) local obj = p if (obj == nil) then obj = {name="ChenHao", age=37, handsome=true} end self.__index = self return setmetatable(obj, self)endfunction Person:toString() return self.name .." : ".. self.age .." : ".. (self.handsome and "handsome" or "ugly")endme = Person:new()print(me:toString())kf = Person:new{name="King's fucking", age=70, handsome=false}print(kf:toString())
(CSDN-BUG)
协程
接口
- 创建
- coroutine.create 返回thread
- coroutine.swap 返回function , 调用之久resume
- coroutine.resume 切入
- coroutine.yield 切出
- 查询
- coroutine.status
- coroutine.running
实例分析
function foo (a) print("foo", a); return coroutine.yield(2*a);endco = coroutine.create(function (a,b) print("co-body", a, b); local r = foo(a+1); print("co-body-mid", r); local r, s = coroutine.yield(a+b, a-b) print("co-body-end", r, s); return b, "end"; end);print("main 1", coroutine.resume(co, 1, 10))print("main 2", coroutine.resume(co, "e"))print("main 3", coroutine.resume(co, "x", "y"))print("main 4", coroutine.resume(co, "x", "y"))
输出 :
-- main coroutine start -- enter co coroutineco-body 1 10-- call foofoo 2-- yield to main coroutinemain 1 true 4-- resume to co coroutineco-body-mid e-- yield to main coroutine main 2 true 11 -9-- resume to co coroutine co-body-end x y-- yield to main coroutine main 3 true 10 end-- resume to co coroutine failed main 4 false cannot resume dead coroutine
(CSDN-BUG)
模块
加载模块
require (不重复的)加载模块文件
下理解是错误的( 虽然这种解释有利于理解文件 + table的常规模块文件) :
fp=require(“my”)-- 等价于 :fp= (function()--my.lua文件内容--end)
证明 :
一个仅仅定义了一个全局变量的模块mud.lua
a = 'test mudle string '
如果require相当于以文件内容定义了一个匿名函数,那么这个文件内部的所有变量定义可见权限都应该限于这个文件所定义的这个函数中。然而 :
调用mud 主文件main.lua
requrie ("mud")-- mud.lua 定义的a 是个全局可见的a。print(a)
dofile 加载并执行文件
loadfile 加载不执行文件
规范的模块
table主导,不污染全局环境的模块
- 利用module函数简写
-- in module xxx.lua-- user can change file name as he need local ModuleName = ... -- module suit require parametermodule(ModuleName ,package.seeall) -- all interfaces/variables are in file are in namespace ...function TestPrint() Print(ModuleName)end-- while use the modulelocal xxx=require("xxx")xxx.TestPrint()
- 全部手打
local M = {}; local modelName = ...;_G[modelName] = M; -- 保证外部使用require的参数可以引用模块内接口function M.quit() print("quit");endfunction M.play() print("play"); M.quit() -- 必须写明属于 Mendreturn M; -- 返回模块table ,不必须,但是支持引用者本地用自己名字保存
- lua语言学习笔记
- Lua - 语言学习笔记
- lua语言学习笔记
- Cocos2dx学习笔记33 Lua语言讲解
- 【学习笔记】系列七:Lua 语言 15 分钟快速入门
- LUA语言学习教程
- LUA语言学习教程
- LUA语言学习教程
- LUA语言学习教程
- Lua语言学习<1>
- 为什么学习lua语言
- Lua 语言学习总结
- Lua学习笔记——C语言与Lua的交互
- lua学习笔记(2)——C语言调用lua的使用和测试
- Lua学习笔记(1)
- Lua学习笔记一
- Lua学习笔记一
- Lua学习笔记一
- arcgis api for JavaScript相关
- Android SwipeRefreshLayout下拉刷新(两种不阻碍线程的方式)
- Android apk动态加载机制的研究
- C++primer plus第六版课后编程练习答案2.5
- oracle表分区详解
- Lua - 语言学习笔记
- iOS 数据缓存
- 学安卓之路
- Android UI性能优化
- 安卓手机连接蓝牙打印机实现打印功能
- tomcat如何配置环境变量
- Java游戏服务器-百万规模实时排行榜实现
- Linux下python升级至2.7步骤
- 蓝桥杯入门训练 Fibonacci数列