函数
lua
语言中,函数是对语句和表达式进行抽象的主要方式。
多返回值
lua
语言中一种与众不同又非常有用的特性是允许一个函数返回多个结果
string.find
- 匹配模式在字符串中起始字符和结尾字符的索引
当函数作为一条单独语句调用时,其所有返回值都会被丢弃;当函数作为表达式调用时,将只保留函数的第一个返回值;只有当函数调用是一系列表达式中的最后一个表达式时,其所有返回值才会被捕获。
所谓一些列的情况:
- 多重赋值
- 函数调用时传入的实参列表
- 表构造器
return
语句
return
语句后面内容不需要加括号,否则会导致额外的行为。
可变长参数函数
lua
语言中,函数可以是可变长参数函数,即可以支持参数数量可变的参数。
1 2 3 4 5 6 7 |
function add(...) local s = 0 for _,v in ipairs{...} do s = s + v end return s end |
参数列表中的三个点
...
表示该函数的参数是可变长的。当这个函数被调用时,
lua
内部会把它的所有参数收集起来,把这些被收集起来的参数称为函数的额外参数。
当函数需要用到这些参数时,还是要用到三个点...
,并需要把三个点...
当作表达式来使用,如上述{...}
。不过,需要注意的是,在某些情况下,如果可变参数中包含无效的
nil
,那么{...}
获得的表可能不再是一个有效的序列。
1 2 3 |
function foo(...) local a,b,c = ... end |
table.pack
像
{...}
一样保持所有的参数,然后将其放在一个表中返回,它还保存一个表示参数个数的额外字段"n"
1 2 3 4 5 6 7 |
function nonils(...) local arg = table.pack(...) for i = 1,arg.n do if arg[i] == nil then return false end end return true end |
select
函数
select
总是具有一个固定的参数selector
,以及数量可变的参数。如果selector
是数值n,那么函数select
则返回第n个参数后的所有参数;否则,selector
应该是字符串“#”
,以便select
返回额外参数的总数。
1 2 3 4 5 6 7 8 |
print(select(1,"a","b","c")) //a b c print(select(2,"a","b","c")) //b c print(select(3,"a","b","c")) //c print(select("#","a","b","c")) //3 |
unpack
table.unpack
该函数的参数是一个数组,返回值为数组内的所有元素。
1 2 3 4 |
print(table.unpack{10,20,30}) //10 20 30 a,b = table.unpack{10,20,30} //a=10,b=20,30被丢弃 |
尾调用
lua
语言支持尾调用消除。当一个函数的最后一个动作是调用另一个函数而没有再进行其他工作时,就形成了尾调用。
1 2 3 4 |
function f(x) x = x + 1; return g(x) end |
刚g返回时,程序的执行路径会直接返回到调用f的位置。
lua
语言解释器,就是利用了这个特点,使得在进行尾调用时不使用额外的栈空间,将这种实现称为尾调用消除。
1 2 3 4 5 |
function foo(n) if n > 0 then return foo(n-1) end end |
由于尾调用不会使用栈空间,所以一个程序中能够嵌套的尾调用的数量是无限的。
关于尾调用消除的一个重点就是如何判断一个调用是尾调用。很多函数之所以不是尾调用,是由于这些函数在调用之后还进行了其他工作。
输入输出
简单I/O模型
简单模型模拟了一个当前输入流和当前输出流,其
I/O
操作是通过这些流实现的。
I/O
库把当前输入流初始化为进程的标准输入(C里面的stdin
),将当前输出流初始化为进程的标准输出(C语言的stdout
)。因此,当执行io.read()
这样的语句时,就可以从标准输入中读取一行。
io.input
和io.output
可以改变当前的输入输出流。调用io.input(file_name)
会以只读模式打开指定文件,并将文件设置为当前输入流。之后,所有的输入都将来自该文件,除非再次调用io.input
。
io.output
的逻辑和io.input
的类似,如果出现错误,这两函数都会抛出异常。如果想处理这些异常,则必须使用完整I/O
模型。
io.write
可以读取任意数量的字符串(或者数字)并将其写入当前输出流。由于调用该函数时可以使用多个参数,因此应避免io.write(a..b..c)
,而应使用io.write(a,b,c)
。
io.read
可以从当前输入流中读取字符串,其参数决定了要读取的数据:
a
- 读取整个文件
l
- 读取下一行(丢弃换行符)
L
- 读取下一行(保留换行符)
n
- 读取一个数值
num
- 以字符串读取num个字符
完整I/O模型
可以使用
io.open
来打开一个文件,该函数仿造了C语言中的fopen
函数。
- 参数一:待打开的文件
- 参数二:模式
- 只读
r
- 只写
w
- 追加
a
- 打开二进制文件
b
在打开文件后,可以使用方法
read
和write
从流中读取和向流中写入(需要使用冒号运算符将它们当作流对象的方法来调用。)
1 2 3 |
local f = assert(io.open(filename,"r")) local t = f:read("a") f:close() |
函数
io.input
和io.output
允许混用完整I/O
模式和简单I/O
模式
其他文件操作
io.tmpfile
- 返回一个操作临时文件的句柄,该句柄是以读/写模式打开的。当程序允许结束后,该临时文件会被自动移除(删除)。
flush
- 将所有缓存数据写入文件
setvbut
- 用于设置流的缓冲模式
- 参数一:
no
表无缓冲,full
表在缓冲区满时或者显示地刷新文件时才写入数据,line
表输出一直被缓冲直到遇到换行符或从一些特定文件中读取到了数据。 - 参数二:可选参数,用于指定缓冲区大小
seek(whence,offset)
- 用来获取或设置文件地当前位置
whence
取值"set"
时,表相对文件开头地偏移;取值"cur"
时,表相对文件当前位置地偏移;取值"end"
时,表相对文件尾部的偏移
其他系统调用
os.exit
- 用于终止程序的执行
os.getenv
- 用于获取某个环境变量,该函数的输入参数是环境变量的名称
1 |
print(os.getenv("HOME")) |
系统命令
os.execute
- 用于运行系统命令
- 参数表示待执行命令的字符串,返回值为命令允许结束后的状态。
1 2 3 |
function createDir(dirname) os.execute("mkdir " .. dirname) end |
io.popen
- 运行一条命令,该函数还可以重定向命令的输入/输出
1 2 3 4 5 6 |
local f = io.popen("dir /B","r") local dir = {} for entry in f:lines() do dir[#dir + 1] = entry end |
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ CLion:配置C++下lua开发环境06/03
- ♥ Lua_基础 类型&&值09/26
- ♥ Lua_调用 C++函数:获取返回值10/09
- ♥ Lua_调用 C++函数:传递表&&参数类型检测10/06
- ♥ C++_调用 Lua内容:全局变量 获取&&设置10/09
- ♥ Lua_调用 C++如何和Lua结合09/27