2008年偶然接触lua,但一直未在工作中使用。网上介绍lua有很多优点
我想lua的优秀一定有其优秀的dna。
虽然lua几个大版本之间有可能存在不兼容,但是他优秀的dna应该还是在早期版本上找到。因此我开始看lua1.0的相关文档,代码。我希望能够坚持,最好能够多阅读几个版本。
-------------------------------------------------------------------------------
Lua1.0从来没有公开发不过。Lua1.0的代码是1993年7月28日的一份代码备份。
这份代码作为历史的古董,并且为了庆祝Lua发布十周年,特此发布出来。
在这份代码里,除了测试程序之外没有任何文档。
但是Lua1.1的手册可能同样适用于与Lua1.0。
lexer 和 parser的源码已经丢失,但是语法定义可以在 y_tab.c 和 yyreds里找到。
代码可以在RedHat 5.2系统上用gcc 2.7.2.3编译,运行。但是可能无法在较新的系统上
运行,因为代码里假定stdin 和 stdout 是常量,然而ANSI C代码没有指定他们必须是常
量。如果make失败,试一下fixed文件夹下的代码。可以通过make diff看一下他们之间的差别。
执行"make test",可以看一下Lua代码执行的结果。
-------------------------------------------------------------------------------
以上摘自Lua1.0 README 2012.08.16
这部分代码在vc下编译也是没问题的。
-------------------------------------------------------------------------------
Makefile
make all 编译生成lua可执行程序
make test 执行测试脚本sort.lua,globals.lua,array.lua,save.lua,test.lua
当然,我们可以手动执行某一个脚本,如 ./lua array.lua
make clean 清楚所有编译产生的文件,包括gdb调试文件。
make diff 如README里所说。
首先看一下array.lua的代码
$debug
a = @()
i=0
while i<10 do
a[i] = i*i
i=i+1
end
r,v = next(a,nil)
while r ~= nil do
print ("array["..r.."] = "..v)
r,v = next(a,r)
end
$debug
--在lua中起什么作用,暂时不清楚 2012.08.16
a = @()
--在lua中起什么作用,暂时不清楚,但是根据代码上下文,应该是定义了一个数组a
2012.08.16
--定义table的语法,Lua通过table来实现数组
--在Lua中习惯上数组的下标从1开始,Lua的标准库与此习惯保持一致。
因此如果你的数组下标也是从1开始你就可以直接使用标准库的函数,
否则就无法直接使用
i=0
while i<10 do
a[i] = i*i
i=i+1
end
--上面这个代码在非交互式模式下,是一个语句块,在交互模式下i=0应该是一个独立的
语句块。这些概念我是在lua5.1手册看到。先不管 2012.08.16
--实现了为数组a的赋值
--需要仔细关注table的
r,v = next(a,nil)
--next是一个什么函数?作用?2012.08.16
--在代码里应该是返回数组a的索引和值,因为lua里function可以返回多个值。2012.08.16
--next(a,nil)应改返回数组a的第一个索引以及第一个值。2012.08.16
--lua5.1 11..1
--且数组不必事先指定大小,大小可以随需要动态的增长
--可以根据需要定义数组的下标从0,1或者任意其他的数值开始
--next的实现在hash.c文件lua_next函数
print ("array["..r.."] = "..v)
--首先..是一个连接符号,挺像c++,java里的多个字符串相加的效果。
--如果连接符号左右是数字,数值,将转化为字符串。2012.08.16
--比c里打印数值要简单,如何实现打印不同格式的数值呢?2012.08.16
貌似lua代码里不支持中英文混排,起码在lua1.0里是这样。
k,v=nextvar(k)
while k do
print(k)
k,v=nextvar(k)
end
从文件名到代码,不难理解程序的本意就是将所有全局变量打印出来。
以下是运行结果,从结果看出lua中的全局变量包括所有的lib函数(strlib,iolib,mathlib),
以及lua.c里注册的c函数,最后还有本段lua代码产生的全局变量。
在lua代码里,如果没有声明为local,就是全局的。
在上面的截图中,只看到了全局变量k,没有看到v,不知是什么原因?
nextvar 访问的应该是个table。
在lua里table,hash应该是灵魂,opcode应该是灵魂寄住的地方,给了灵魂以生命。
因此table,hash,opcode这些部分我在lua1.0里尽量晚的介入,前期尽量从使用角度体会,而不是从实现角度分析。
y_tab & lex_yy 由于没有其产生的源码,在lua1.0里我不会介入这部分,只把它当做一个黑盒使用。
根据以上的一些因素,以后我选择lib函数(strlib,iolib,mathlib)中的iolib进行初步的使用,实现lua与c的交互,这个才是大家喜欢使用lua的原因吧!
根据iolib.c了解到 iolib 注册的函数有
readfrom
writeto
read
write
execute
remove
在这里,readfrom,writeto是可以指定输入输出文件的,
我为了方便,并没有使用这两个接口进行测试,直接使用了默认的stdin和stdout进行io测试。
还记得..是连接符吗?
write("sin (3) = "..sin(3).."\n")
会在终端上输出sin (3) = 0.14112
注意write接口不会自动增加换行符。例如下面的测试,如果想写入一个数字,然后换行,只能这样写。
write("666.123","f<10.3")
write("\r\n")
write("666.123","f>10.3")
write("\r\n")
write("666.123","f|10.3")
write("\r\n")
上面的f>,f<,f|叫做格式化写。看一下输出就知道什么意思了。
这个的f可不是format的意思,是float的意思,10表示输入字符串的宽度,.3表示小数点后的位数
觉得lua代码神奇的人,看看对应的c实现,是不是觉得也很容易。
如果想给写脚本的人提供方面,用你写的c去实现吧。
格式化读取
readtest = read("f5");
print("readret= "..readtest)
无格式化读取
readtest = read();
print("readret= "..readtest)
如果你输入空格,回车后,程序一直等待输入。因为lua实现会忽略前面输入的所有空格
另外write和read基于现在的功能,还是有优化空间的,毕竟是1.0版本。
大家可以测试一下。
如何实现一个lua脚本的循环执行呢,下面这个代码可以做到
loop.lua
print("I am looping")
execute('./lua loop.lua')
然后在终端输入 ./lua loop.lua ,loop.lua这个脚本将被反复执行,直到你按下ctrl+c
看一下execute对应的c代码,大家就都清楚是怎么回事了。