Part I: The Language
Chapter 1: Getting Started
Hello,world!
print("Hello World")
function 函数
-- defines a factorial function
function fact (n)
if n == 0 then
return 1
else
return n * fact(n-1)
end
end
print("enter a number:")
a = io.read("*number") -- read a number
print(fact(a))
1.1 Chunks 块
块就是单条语句,或语句及函数的混合体。
分号可要可不要
a = 1
b = a*2
a = 1;
b = a*2;
a = 1; b = a*2
a = 1 b = a*2 -- ugly, but valid
分号一般只用于分隔同一行上的多条语句。如:a = 1; b = a*2
块可以任意大
Lua 作为一种数据描述语言,数兆大小的块并不少见。
Lua 交互环境
不带参数运行lua 解释器:
Lua 5.1 Copyright (C) 1994-2006 Lua.org, PUC-Rio
>
Ctrl + Z 退出交互模式
dofile 函数
dofile 函数对于测试一段代码特别有用
lib1.lua 文件:
function norm (x, y)
return (x^2 + y^2)^0.5
end
function twice (x)
return 2*x
end
> dofile("lib1.lua") -- load your library
> n = norm(3.4, 1.0)
> print(twice(n)) --> 7.0880180586677
这样可以一边编写代码,一边运行交互环境测试。
1.2 Some Lexical Conventions 语法
标识符和C 语言类似,除了以下两点:
1. 避免用一个下画线加大写字母的形式,如_VERSION,这是保留字。
2. 不要用单个下划线做标识符 “_” ,这是dummy variables
i j i10 _ij
aSomewhatLongName _INPUT
保留字
and break do else elseif
end false for function if
in local nil not or
repeat return then true until
while
Lua 大小写敏感
and 是保留字,但And 和AND 是不同的标识符。
单行注释 --
print(10) -- 这是注释
多行注释
--[[
print(10) -- 没有输出
--]]
取消多行注释
加一个 “-”
---[[
print(10) -->输出10
--]]
1.3 Global Variables
全局变量不用声明既可使用。
访问未初始化变量不是错误,而是得到一个nil 值。
全局变量不用删除,只需赋nil 值:
b = nil
print(b) --> nil
全局变量是存在的,当且仅当其有non-nil 值。
1.4 The Stand-Alone Interpreter
参见 p7
Chapter 2: Types and Values
Lua 是动态类型语言,无需类型定义。
八种基本类型
nil, boolean, number, string, userdata, function, thread, and table.
打印值的类型
print(type("Hello world")) --> string
print(type(10.4*3)) --> number
print(type(print)) --> function
print(type(type)) --> function
print(type(true)) --> boolean
print(type(nil)) --> nil
print(type(type(X))) --> string
最后一行返回string, 因为type 返回值是string,与X 是什么值无关。
print(type(a)) --> nil ('a' is not initialized)
a = 10
print(type(a)) --> number
a = "a string!!"
print(type(a)) --> string
a = print -- yes, this is valid! – 将一个函数赋值给一个变量
a(type(a)) --> function
2.1 Nil
给一个全局变量赋一个nil 值会删除这个全局变量。
2.2 Booleans
false 和 nil 都表示假,其它值都表示真。
注意:0 表示真,空串也表示真。
2.3 Numbers
Lua 只有双精浮点型,没有整型。
4 0.4 4.57e-3 0.3e12 5e+20
+10 是10 是另一种写法
2.4 Strings
string 中可以包含任意二进制数值,可以含 有0
string 是不可变值,不可以改变串中的任一字符。
a = "one string"
b = string.gsub(a, "one", "another") -- change string parts
print(a) --> one string
print(b) --> another string
string 可以只含一个字符,也可以是整本书的长度。
长度为100K 或 1M 的串在lua 程序中并不少见。
无需关心string 的内存分配和释放,Lua自动内存管理会负责。
String 的两种写法
a = "a line"
b = 'another line'
以下两个串有相同值
"alo/n123/""
'/97lo/10/04923"'
其中 /049 而不是/49 是因为后面有数值23,
带有换行的串
page = [[
<html>
<head>
<title>An HTML Page</title>
</head>
<body>
<a href="http://www.lua.org">Lua</a>
</body>
</html>
]]
write(page)
可以包含任意字符的串
[[
]]
[=[
]=]
[[==
==]]
[[===
===]]
….
后面的串里面可以包含前面的串
a =
[=[
123
]=]
print(a)
strings 和numbers 间的自动类型转换
print("10" + 1) --> 11
print("10 + 1") --> 10 + 1
print("-5.3e-10"*"2") --> -1.06e-09
print("hello" + 1) -- ERROR (cannot convert "hello")
连接两个串的运算符 ..
print(10 .. 20) --> 1020 -- 自动类型转换
print(‘he’..’llo’) -- 输出hello
注意10 .. 20 中间有空格,不然lua 认为第一个点是小数点。
tonumber tostring 显示类型转换
line = io.read() -- read a line
n = tonumber(line) -- try to convert it to a number
if n == nil then
error(line .. " is not a valid number")
else
print(n*2)
end
print(10=="10") --> false
print(tostring(10) == "10") --> true
print(10 .. "" == "10") --> true
计算string长度的运算符#
a = "hello"
print(#a) --> 5
print(#"good/0bye") --> 8
2.5 Tables
1 是表的第一个索引
a = {x=1; y=2}
print(a[1]) -- 输出nil
表的索引可以是除nil 外的任意类型。
表是lua 的唯一数据结构。
Lua 使用表来表示模块,包,对象列表
io.read 表示使用read 作为索引查表io
lua 中表是对象,而不是值或变量
创建表的运算符{}
a = {} -- create a table and store its reference in 'a'
k = "x"
a[k] = 10 -- new entry, with key="x" and value=10
a[20] = "great" -- new entry, with key=20 and value="great"
print(a["x"]) --> 10
k = 20
print(a[k]) --> "great"
a["x"] = a["x"] + 1 -- increments entry "x"
print(a["x"]) --> 11
表不用声明,实际上没有方法声明一个表,只能用{} 创建。
表是一种引用类型
a = {}
a["x"] = 10
b = a -- 'b' refers to the same table as 'a'
print(b["x"]) --> 10
b["x"] = 20
print(a["x"]) --> 20
a = nil -- only 'b' still refers to the table
b = nil -- no references left to the table
当表不存在它的引用时,自动删除并回收内存
表的大小是自动增长的
a = {} -- empty table
-- create 1000 new entries
for i=1,1000 do a[i] = i*2 end
print(a[9]) --> 18
a["x"] = 10
print(a["x"]) --> 10
print(a["y"]) --> nil
和全局变量一样,赋一个nil 给表中的一个元素将会删除这个元素。
赋一个nil 给一个表,将会删除这个表。
记录类型 —— 表的一个语法糖
a.name 是a["name"] 的另一种写法。
a.x = 10 -- same as a["x"] = 10
print(a.x) -- same as print(a["x"])
print(a.y) -- same as print(a["y"])
a = {}
x = "y"
a[x] = 10 -- put 10 in field "y"
print(a[x]) --> 10 -- value of field "y"
print(a.x) --> nil -- value of field "x" (undefined)
print(a.y) --> 10 -- value of field "y"
获得表的最后一个索引的运算符#
最后一个索引等于表的元素个数,因为1 是表的第一个索引。
获得表的最大数值索引table.maxn
a = {}
a[10000] = 1
print(table.maxn(a)) --> 10000
遍历表
-- read 10 lines storing them in a table
a = {}
for i=1,10 do
a[i] = io.read()
end
-- print the lines
for i=1, #a do
print(a[i])
end
print(a[#a]) -- 输出表a 的最后一个元素
a[#a] = nil -- 删除表的最后一个元素
a[#a+1] = v -- 在末尾添加一个 'v'
读入文件前10 行的另一种方法
a = {}
for i=1,10 do
a[#a+1] = io.read()
end
2.6 Functions
函数可以赋值给一个变量,可以通过参数传递给另一个函数,可以作为函数的返回值。
Lua 中既可调用lua 中定义的函数,也可以调用C 语言中定义的函数。
2.7 Userdata and Threads
以后讨论