Lua中的table不是一种简单的数据结构,它可以作为其它数据结构的基础。如数组、记录、线性表、队列和集合等,在Lua中都可以通过table来表示。

1、数组

使用整数来索引table即可在Lua中实现数组。因此,Lua中的数组没有固定的大小,如:

a = {}
for i = , do
a[i] =
end
print("The length of array 'a' is " .. #a)
--The length of array 'a' is 1000

在Lua中,可以让任何数作为数组的起始索引,但通常而言,都会使用1作为其起始索引值。

而且很多Lua的内置功能和函数都依赖这一特征,因此在没有充分理由的前提下,尽量保证这一规则。

下面的方法是通过table的构造器来创建并初始化一个数组的,如:

squares = {, , }

function  wyq( ... )
for i=,select('#',...) do
local temp = select(i,...)
if(type(temp)=="string") then
print("这是字符串 = "..temp)
elseif(type(temp)=="table") then
for j=,table.maxn(temp) do
print(temp[j])
end
else
print("这是数字 = "..temp)
end
end
end wyq(squares,,"hello")
--输出结果
--
--
--
--这是数字 = 2
--这是字符串 = hello

2、二维数组

在Lua中我们可以通过两种方式来利用table构造多维数组。其中,第一种方式通过“数组的数组”的方式来实现多维数组的,即在一维数组上的每个元素也同样为table对象,如:

mt = {}
function eeeee( ... )
local N =select(,...)
local M =select(,...)
for i = , N do
mt[i] = {}
for j = , M do
mt[i][j] = i * j
end
end
end eeeee(,) for i=,table.maxn(mt) do
local len = table.maxn(mt[i])
for j=,len do
print(mt[i][j])
end
end

第二种方式是将二维数组的索引展开,并以固定的常量作为第二维度的步长,如:

mt = {}
for i = , N do
for j = , M do
mt[(i - ) * M + j] = i * j
end
end

3、链表

由于table是动态的实体,所以在Lua中实现链表是很方便的。其中,每个结点均以table来表示,一个“链接”只是结点中的一个字段,该字段包含对其它table的引用,如:

list = nil
for i = , do
list = { next = list, value = i}
end local l = list
while l do
print(l.value)
l = l.next
end
--10 9 8 7 6 5 4 3 2 1

package.path 、 require 、 package.loaded

require到底是如何加载模块的呢?

用require函数只能加载一次,因为它的特性是:    1、require函数会搜索目录加载文件     2、require会判断是否文件已经加载避免重复加载同一文件。

lua文件就相当于c#中的类一样,而require就相当于c#中的using一样

首先,要加载一个模块,就必须的知道这个模块在哪里。知道了这个模块在哪里以后,才能进行正确的加载。当我们写下require “mod”这样的代码以后,Lua是如何找这个mod的呢?

这里就详细的说一说。 在搜索一个文件时,在windows上,很多都是根据windows的环境变量path来搜索,而require所使用的路径与传统的路径不同,require采用的路径是一连串的模式,

其中每项都是一种将模块名转换为文件名的方式。require会用模块名来替换每个“?”,然后根据替换的结果来检查是否存在这样一个文件,如果不存在,就会尝试下一项

。路径中的每一项都是以分号隔开,比如路径为以下字符串:

?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua

那么,当我们require “mod”时,就会尝试着打开以下文件:

mod
mod.lua
c:\windows\mod
/usr/local/lua/mod/mod.lua

可以看到,require函数只处理了分号和问号,其它的都是由路径自己定义的。在实际编程中,require用于搜索的Lua文件的路径存放在变量package.path中,在我的电脑上,print(package.path)会输出以下内容:

;.\?.lua;D:\Lua\5.1\lua\?.lua;D:\Lua\5.1\lua\?\init.lua;D:\Lua\5.1\?.lua;D:\Lua\5.1\?\init.lua;D:\Lua\5.1\lua\?.luac

如果require无法找到与模块名相符的Lua文件,那Lua就会开始找C程序库;这个的搜索地址为package.cpath对应的地址,在我的电脑上,print(package.cpath)会输出以下值:

.\?.dll;.\?.dll;D:\Lua\5.1\?.dll;D:\Lua\5.1\?.dll;D:\Lua\5.1\clibs\?.dll;D:\Lua\5.1\clibs\?.dll;D:\Lua\5.1\loadall.dll;D:\Lua\5.1\clibs\loadall.dll

当找到了这个文件以后,如果这个文件是一个Lua文件,它就通过loadfile来加载该文件;如果找到的是一个C程序库,就通过loadlib来加载。

loadfile和loadlib都只是加载了代码,并没有运行它们,为了运行代码,require会以模块名作为参数来调用这些代码。如果lua文件和C程序库都找不到,怎么办?

我们试一下,随便require一个东西,比如:

require "jellythink"
lua: test.lua:: module 'jellythink' not found:
no field package.preload['jellythink']
no file '.\jellythink.lua'
no file 'D:\Lua\5.1\lua\jellythink.lua'
no file 'D:\Lua\5.1\lua\jellythink\init.lua'
no file 'D:\Lua\5.1\jellythink.lua'
no file 'D:\Lua\5.1\jellythink\init.lua'
no file 'D:\Lua\5.1\lua\jellythink.luac'
no file '.\jellythink.dll'
no file '.\jellythink51.dll'
no file 'D:\Lua\5.1\jellythink.dll'
no file 'D:\Lua\5.1\jellythink51.dll'
no file 'D:\Lua\5.1\clibs\jellythink.dll'
no file 'D:\Lua\5.1\clibs\jellythink51.dll'
no file 'D:\Lua\5.1\loadall.dll'
no file 'D:\Lua\5.1\clibs\loadall.dll'

是的,会报错的。以上就是require的一般工作流程。

自己如何定义require相关lua文件的搜索路径?(package.path

package.path用于指定require搜索的路径。

 package.path = "G:/TestLua/Assets/StreamingAssets/?.lua" --这样就会去G:/TestLua/Assets/StreamingAssets/下搜索lua文件

package.loaded

当我们有一些特殊的需求的时候,就可能会需要反复加载某个lua文件,例如我的文件lua文件动态地改变了,我要立即,或者一些其他特殊原因.

看下例子就知道了:

编写两个lua文件,a.lua和b.lua,代码分别如下

-- a.lua
myname='tom' -- b.lua
require "a"
function MyFunc()
print('my name is '..myname)
end

客户端c#代码为:

private LuaState lua;
private LuaFunction zwhFunc;
void Start()
{
lua = new LuaState();
} public void CallMethod()
{
lua.DoFileFromAge(this, "Demo.lua", delegate(System.Object[] obj) --必须重新加载Demo.lua文件,不然package.loaded是没用的,加载的永远是第一次获取的那一份,DoFileFromAge方法就是重新读取了Demo.lua文件
{
zwhFunc = lua.GetFunction("MyFunc");
zwhFunc.Call();
});
}

场景里面的一个按钮的OnCLick绑定CallMethod方法,点击一次按钮,会输出“my name is tom”,程序一直运行着,不要退!

此时我们去修改一下a.lua文件下的myname值为jerry,然后再点击一下按钮,还是会输出“my name is tom”,可以看出我们虽然修改了myname的值,但是根本没有应用过去,

这也就是require的特性所致吧(require会判断是否文件已经加载避免重复加载同一文件),如果想myname改变的值能够在程序运行的时候立马应用,这就用到了package.loaded

我们修改下b.lua,加个package.loaded["a"]  = nil 即可!我觉得这个特性还是在游戏开发的时候用到最好,避免每次修改代码,都需要重新退出再进游戏了,游戏发布之后就可以关了

-- b.lua
package.loaded["a"] = nil
require "a"
function MyFunc()
print('my name is '..myname)
end

此时你修改myname的值,变会立马应用,看到值的变化了!

至于为什么,我们来看下require函数的伪代码就知道了:

-- require和package.loaded的关系
如果没有载入任何Chunk,典型的package.loaded是类似如下的一张表
string table: 00375D48
package table: 00373C30
_G table: 00371FD8
os table:
table table:
math table: 003763C8
coroutine table: 003738A8
debug table: 00376FA0
io table: 00374DC8 -- 当我们require("main")成功后,该表会变回
string table: 00375D58
package table: 00373C38
_G table: 00371FC0
os table:
table table: 003731A0
math table: 003763D8
coroutine table: 003738B0
debug table: 00376FB0
io table: 00374DD8
main true -- 新增表项package.loaded["main"] = true
function require(virname) do
if not package.loaded[virname] then --如果package.loaded[virname]存在的话,就直接返回
return
end
local anyfileloaded = false
patternpath = (replace '?' in package.path to virname)
foreach path in patternpath split by ';' do -- virname如果含有'.', 那么'.'会被替换为'\\'
if ((chunk = loadfile(path)) ~= nil) then
chunk()
package.loaded[virname] = true -- 可以手工设置package.loaded[virname] = false来重复载入该文件
anyfileloaded = true
break
end
end if not anyfileloaded then
print error message
end
end

require是每个页面都需要吗? 

-- 入口方法Start    main.lua

require 'tempage'
require 'tempname‘ function Start()
print('my name is '..myname)
end
-- tempage.lua
myage=
-- tempname.lua
myname='tom'
print('my age is '..myage) --这句话顺利执行,我一直以为需要require myage所在的lua文件,原来不需要,如果tempage.lua加载前的相关lua文件require进了myage所在的lua文件,那么就不需要在require了!这里main.lua先require过了tempage.lua了,所以这里能访问到myage变量! --打印结果
--my age is 199
--my name is tom

collectgarbage

luanet

 

测量lua脚本执行的时间

local x = os.clock()
local s =
for i=, do s = s + i end
print(string.format("elapsed time: %.2f\n", os.clock() - x))

http://blog.sina.com.cn/s/blog_3d2d5d790100idjv.html

Lua3的更多相关文章

  1. wireshark lua脚本

    1.目的:解析rssp2协议   2.如何使用wireshark lua插件 将编写的(假设为rssp2.lua)lua文本,放入wireshark 安装目录下,放哪里都行只要dofile添加了路径. ...

  2. android 图片性能优化

    本章讲述在android开发中,图片处理方面的优化.包括知识点为大图加载,图片压缩,图片缓存处理及开源图片处理框架Universal-Image-Loader. 1.图片引发的内存不足 当在andro ...

  3. 【转】封装Lua for C#

    原文:http://blog.csdn.net/rcfalcon/article/details/5583095 为了搞懂LUA在我们的GDEX中到底怎么用,我决定研究一下如何比较好的在WPF里封装一 ...

  4. 《The Evolution of Lua》读书笔记 1

    lua的优点: 可移植性 容易嵌入 体积小 高效率 这些优点都来自于lua的设计目标:简洁.从Scheme获得了很多灵感,包括匿名函数,合理的语义域概念   lua前身: 巴西被禁运,引入计算机软件和 ...

  5. 五毛的cocos2d-x学习笔记01-创建项目

    终于准备开始学习cocos2d-x了.因为想和同学一起做游戏参加比赛,所以打算学习很热的Cocos2d-x.因为已经学习了C++,所以我想入门应该不是很困难.再加上官网有中文教程以及多不胜数的游戏开发 ...

  6. Lua学习系列(一)

    从现在开始,打算学习一门新的脚本语言-lua. 1.什么是lua? a) lua1 • Lua 1.0 was implemented as a library, in less then 6000 ...

  7. Lua与.net的CLR相互调用

    工程环境搭建: 下载luainterface-1.5.3.zip文件,使用到的dll为Built目录下的LuaInterface.dll.lua51.dll.luanet.dll LuaInterfa ...

  8. 2018/1/9 redis学习笔记(一)

    本文不涉及redis基本命令以及javaapi的解释操作; 首先介绍下redis,一个nosql非关系型数据库,运行在缓存中,特点就是可存储的数据结构类型很多,做为KEY-VALUE数据库,它的键只能 ...

  9. 热更新应用--热补丁Hotfix学习笔记

    一.热补丁简介 热补丁主要是用于将纯C#工程在不重做的情况下通过打补丁的形式改造成具备lua热更新功能工程,主要是让原来脚本中Start函数和Update函数等函数代码块重定向到lua代码. 二.第一 ...

随机推荐

  1. selenium 打开浏览器报错java.lang.NoSuchMethodError: org.openqa.selenium.chrome.ChromeOptions.addArguments([Ljava/lang/String;)

    java.lang.NoSuchMethodError: org.openqa.selenium.chrome.ChromeOptions.addArguments([Ljava/lang/Strin ...

  2. Android 编辑框(EditText)属性学习

    EditText的属性很多,这里介绍几个:android:hint="请输入数字!"//设置显示在空间上的提示信息android:numeric="integer&quo ...

  3. React的安装

    创建: 2019/05/01 完成: 2019/05/01 create-react-app  学习及创建单页app npx create-react-app my-app cd my-app npm ...

  4. JS将unicode码转中文方法

    原理,将unicode的 \u 先转为 %u,然后使用unescape方法转换为中文. ? 1 2 3 4 <script type="text/javascript"> ...

  5. GDB调试手册[转]

    Linux 包含了一个叫gdb 的GNU 调试程序.gdb 是一个用来调试C和C++程序的强力调试器.它使你能在程序运行时观察程序的内部结构和内存的使用情况.以下是 gdb 所提供的一些功能:它使你能 ...

  6. 第47章 QR-Decoder-OV5640二维码识别—零死角玩转STM32-F429系列

    第47章     QR-Decoder-OV5640二维码识别 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.y ...

  7. 前端css优先级以及继承

    1.css优先级以及继承 css具有两大特性:继承性和层叠性 继承性 继承:给父级设置一些属性,子级继承了父级的该属性,这就是我们的css中的继承. 有一些属性是可以继承下来 : color . fo ...

  8. 出门旅行(tour)

    出门旅行(tour) 题目描述: 在神奇的 oi 国度,有 n 个城市 m 条双向道路,每条道路连接了两个不同的城市.寒假到了,小 S 决定出门旅游一趟.因为以往跟团旅游多了,这次小 S 决定自驾游. ...

  9. css3 媒体查询的学习。

    1.什么是媒体查询 媒体查询可以让我们根据设备显示器的特性(如视口宽度.屏幕比例.设备方向:横向或纵向)为其设定CSS样式,媒体查询由媒体类型和一个或多个检测媒体特性的条件表达式组成.媒体查询中可用于 ...

  10. python中的字符串内置方法小结

    #!/usr/local/bin/python3 # -*- coding:utf-8 -*- ''' name="my wife is mahongyan" ---------- ...