1.1 程序段
遵照惯例,写一个输出 Hello World 的程序
print("Hello World")
将包含以上程序代码的文件保存成 .lua
为后缀的文本文件即可,此处我们保存成 hello.lua
,在命令行中,进入相应的文件夹后执行以下命令:
% lua hello.lua
得到的结果为:
Hello World
除此之外,我们也可以在交互式模式( interactive mode )下运行独立解释器。当不带参数调用 lua 时,我们可以看到以下输出:
% lua
Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
>
每输入一条命令都会在按下回车后立即执行,如果不是一个完整的语句则会多一个箭头:
> a =
>> 6
> = a
6
我们通过输入EOF控制符(Windows 环境下使用 Ctrl + Z
)或者调用操作系统库的 exit 函数os.exit()
退出交互模式。
从 5.3 版本开始,可以直接在交互模式下输入表达式,Lua 会输出表达式的值,但之前的老版本中需要在开头输入一个=
,为了向下兼容,Lua 5.3 也支持这种写法。
附 1:Lua 命令行参数
lua [options] [script [args]]
options | 功能 | 示例 |
---|---|---|
-i | 执行完script之后进入交互模式 | lua -i test.lua |
-e | 直接在命令行中传入代码 | lua -e "print("Hello World")" |
-l | 加载一个文件 | lua -l test |
注意在-l
为参数的时候文件名不需要加.lua
否则将会报错
Lua Scripts>lua -l test.lua
lua: module 'test.lua' not found:
no field package.preload['test.lua']
no file '.\test\lua.lua'
no file 'C:\Program Files (x86)\Lua\5.1\lua\test\lua.lua'
no file 'C:\Program Files (x86)\Lua\5.1\lua\test\lua\init.lua'
no file 'C:\Program Files (x86)\Lua\5.1\test\lua.lua'
no file 'C:\Program Files (x86)\Lua\5.1\test\lua\init.lua'
no file 'C:\Program Files (x86)\Lua\5.1\lua\test\lua.luac'
no file '.\test\lua.dll'
no file 'C:\Program Files (x86)\Lua\5.1\test\lua.dll'
no file 'C:\Program Files (x86)\Lua\5.1\loadall.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\test\lua.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\loadall.dll'
no file '.\test\lua51.dll'
no file 'C:\Program Files (x86)\Lua\5.1\test\lua51.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\test\lua51.dll'
no file '.\test.dll'
no file 'C:\Program Files (x86)\Lua\5.1\test.dll'
no file 'C:\Program Files (x86)\Lua\5.1\loadall.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\test.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\loadall.dll'
no file '.\test51.dll'
no file 'C:\Program Files (x86)\Lua\5.1\test51.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\test51.dll'
stack traceback:
[C]: ?
[C]: ?
Lua Scripts>
另一种加载文件的方法就是使用dofile()
,在交互模式下输入命令:
> dofile("test.lua")
Hello World
>
1.2 词法规范
Lua 语言中的标识符是由字母、数字和下划线组成的字符串(不能以数字开头),下划线加大写字母(例如:__VERSION)组成的标识符通常被Lua语言用作特殊用途,应尽量避免使用。
附 2:Lua 保留字
and break do else elseif
end false goto for function
if in local nil not
or repeat return then true
until while
Lua 语言对大小写敏感,所以标识符使用AND
并不会与and
发生冲突。
Lua 中的单行注释用--
,多行注释用--[[
和--]]
包裹住,例如:
--[[
print("Hello World")
--]]
这段代码并不会被执行,因为被注释掉了,如果想要重新启用可以再增加一个-
---[[
print("Hello World")
--]]
一般情况下不需要使用分号来分隔语句,但是为了易读,可以在一行中出现多个语句时使用分号进行分隔。
1.3 全局变量
在 Lua 语言中,全局变量不需要声明就可以使用,使用未经初始化的全局变量也不会导致错误。当使用未初始化的全局变量时会得到nil
:
> = type(a)
nil
>
把nil
赋给全局变量时,Lua就会回收该全局变量。
1.4 类型和值
Lua 语言是一种给动态类型语言,在这种语言中没有类型定义,每个值都带有其自身的类型信息。
Lua 语言有8中基本类型:nil
空、boolean
布尔、number
数值、string
字符串、userdata
用户数据、function
函数、thread
线程和table
表
使用函数type()
就可以获取一个值对应的类型名称。
注意:Type()函数的返回值类型是string 所以作比较时要使用 type(1) == "number"
userdata 类型允许把任意的C语言数据保存在 Lua 语言变量中。在 Lua 语言中,用户数据类型除了赋值和相等性测试外,没有其他预定义操作。用户数据被用来表示由应用或C语言编写的库所创建的新类型。
1.4.1 nil
nil 是一种只有一个 nil
值的类型,它的主要作用就是与其他值有所区分。Lua 语言用nil
来表示无效值的情况。
Boolean
Boolean 类型有两个值,true
和false
,它们分别代表了真和假。在 Lua 中只有false
和nil
被视为假,其他都视为真,包括0和空字符串。
> if nil or false then
>> print("true")
>> else
>> print("false")
>> end
false
>
Lua 支持常见的逻辑运算符and
、or
和not
。and
和or
遵循短路原则。
练习
- 练习 1.1:运行阶乘的示例并观察,如果输入负数,程序会出现什么问题?试着修改代码来解决问题。
如果输入负数就会发生栈溢出,所以应该对输入的数据加以限制,我写的代码如下:
function fact(x)
if(type(x) == "number") then --首先要保证它是一个数字
if x % 1 < 1e-6 then --对1取余判0,保证它是一个整数
if x == 0 or x == 1 then
return 1
elseif x < 0 then --保证它是非负数
print("expected a nonnegative number")
else
return x * fact(x-1)
end
else
print("not a integer")
end
else
print("not a number")
end
end
print("Please enter a number")
a = io.read("*n") --虽然这里已经限制了读取数字,但是还是会接收到键盘输入的字符
print(fact(a))
- 练习 1.2:分别使用
-l
参数和dofile
运行twice
示例,并感受你喜欢哪种方式。
参考附1的内容
- 练习 1.3:你是否能举出其它使用
--
作为注释的语言?
sql
- 练习 1.4:以下字符串中哪些是有效的标识符?
___
_end
End
end
until?
nil
NULL
one-step
有效:
___
_end
End
NULL
无效:end
until?
nil
one-step
首先保留字end
和nil
是肯定不能做标识符的,until?
中?
不能出现在标识符中,one-step
中的-
会被识别为减号所以不能出现在标识符中,应改用下划线。
- 练习 1.5:表达式
type(nil) == nil
的值是什么?你可以直接在 Lua 中运行来得到答案,但是你能够解释原因吗?
> = type(nil) == nil
false
>
出现这种情况的原因是,
type()
函数的返回值是string类型,无法直接与nil类型做比较:
> = type(type(nil))
string
>
想要解决这个问题需要将
nil
改为"nil"
> = type(nil) == "nil"
true
>
- 练习 1.6:除了使用函数
type
外,如何检查一个值是否为Boolean类型?
可以使用
==
来判断一个值是否为 Boolean 类型
-- isBoolean.lua
function isBoolean(x)
if x == true or x == false then
return true
else
return false
end
end
测试数据和结果:
> = isBoolean(true)
true
> = isBoolean(false)
true
> = isBoolean(5)
false
> = isBoolean("true")
false
>
- 练习 1.7:考虑如下的表达式:
(x and y and (not z)) or ((not y) and x)
其中的括号是否是必须的?你是否推荐在这个表达式中使用括号?
运算符优先级按从高到低的顺序为:
^
not
-(负数)
*
/
+
-
..
<
>
<=
>=
~=
==
and
or
由此可知not
的优先级比and
和or
要高,从语法的角度说不需要加括号,但是加上括号便于阅读,所以我推荐使用括号。
- 练习 1.8:请编写一个可以打印出脚本自身名称的程序(事先并不知道脚本自身的名称)
脚本的名称存储在arg[0]中
-- test.lua
print(arg[0])
必须要有对应的文件才会有返回结果,不然就会报错。