在Lua中,return语句能返回多个值,这些值能让我们更轻松地完成一些工作。例如在WoW中,我们有时必须把十六进制的字符串转化为红绿蓝三色十进制值。
十六进制字符串的典型例子是“FFCC99”它们两个字符一组,分别代表红色(FF),绿色(CC),蓝色(99)。所以我们需要先截取字符串,string.sub()可以完成这个要求,然后再转化为数字,我们可以用tonumber()。
我们的转换函数定义如下:
> convertHexToRGB=function (hex)
>> local red=string.sub(hex,1,2)
>> local green=string.sub(hex,2,3)
>> local green=string.sub(hex,3,4)
>> local blue=string.sub(hex,5,6)
>> red=tonumber(red,16)/255
>> green=tonumber(green,16)/255
>> blue=tonumber(blue,16)/255
>> return red,green,blue
>> end
稍微说明一下两个函数的语法。string.sub()有三个参数,第一个是要被截取的字符串,第二个参数是开始下标,第三个参数是结束下标,返回值就是截取后的子字符串。而tonumber()有两个参数,第一个是要被转换为数字的字符串,第二个是可选参数,如果没写则默认转化一个十进制字符串为十进制数字,如果写了,则按指定的进制(上面代码中的16就是说按16进制来理解第一个参数)来理解第一个参数字符串,并将它转换为十进制数字。返回值就是转换后的数字。
下面看看测试情况:
> print(convertHexToRGB("FFCC99"))
1 0.8 0.6
> print(convertHexToRGB("FFFFFF"))
1 1 1
> print(convertHexToRGB("000000"))
0 0 0
如果要接收有多个返回值的函数,可以使用下面的语法:
var1,var2,var3,var4=somefunction()
多个返回值在一些特殊的情况下会丢失:
先来看函数的例子:
> print("青苹果","梨",convertHexToRGB("FFFFFF"))
青苹果 梨 1 1 1
> print("青苹果",convertHexToRGB("FFFFFF"),"梨")
青苹果 1 梨
然后再来看看多指派表达式的情况:
> a,b,c,d="青苹果",convertHexToRGB("FFFFFF")
> print(a,d)
青苹果 1 1 1
a,d四个变量都接收到了值。但如果换一下次序:
> a,d=convertHexToRGB("FFFFFF"),"青苹果"
> print(a,d)
1 青苹果 nil nil
我们再一次看到,convertHexToRGB()的三个返回值,只有一个被接收到了。后两个变量都没有值。
l 角色名称
l 角色在团队中的级别
l 角色所属子群
l 角色等级
l 角色职业
l 角色职业
l 角色所在区域名
l 角色是否在线
l 角色是否死亡
l 角色是主战士或主辅助
l 角色是否为物品分配人员
1.
使用哑变量
你会看到类似下面的用法:
> _,g=convertHexToRGB("FFFFFF")
第一个变量的名字就叫_,很奇怪的变量名。但是想想也没问题,因为下划线是合法的标识符,所以用它作为变量是没有问题的,而且由于这样的名字通常都不会在程序里正常使用,所以我们用它来接收那些对我们无用的返回值,这就叫哑变量。实际上这样的使用方式并不被认为是一种好的方法。
2.
使用select()
函数
select()函数用来解决这个问题,它允许你指定从第几个返回值开始取值。这个函数可以接受任意数目的参数,其中第一个参数用来决定函数的行为,当第一个参数为“#”时,select()简单返回其余参数的个数,当第一个参数为一个数字时,select()返回其余从这个位置开始直到最后一个的参数:
> print(select("#","a","b","c"))
3
> print(select(1,"c"))
a b c
> print(select(2,"c"))
b c
> print(select(3,"c"))
c
类似select()这样的函数,它可以接收可变数目的参数,我们现在就来说说如何实现这样的情况。
在Lua中,三个点(…)可以作为函数声明的最后一个参数,用于声明可选的参数。一旦三个点(…)在函数体中使用,在变参空位中提供的参数就会代替它。比如我们想做一个测试的print()函数,它在一开头会打印“测试:”两个字符,可以这样写:
> test_print=function(...)
>> print("测试",...)
>> end
> test_print("苹果","香蕉","梨")
测试 苹果 香蕉 梨
当函数运行时,我们可以用以下的形式来使用三个点(…)
print(…)
--将参数指定给有限数量的变量
var1,var3=…
--将参数指定为一个表中的元素
tbl={…}
> newtable=function(...)
>> return {...}
>> end
测试一下:
> tbl=newtable("苹果","梨")
> for i=1,#tbl do
>> print(tbl[i])
>> end
苹果
香蕉
梨
> test_inputnumber=function(...)
>> local num=select("#",...)
>> print("你输入了" .. num .. "个参数")
>> end
> test_inputnumber(1,4,6)
你输入了6个参数
有了这个信息,我们就可以通过for循环来获得你所你输入的所有参数的值:
> test_select=function(...)
>> for i=1,select("#",...) do
>> print(i,(select(i,...)))
>> end
>> end
在这个for循环中我们使用了两次select(),第一次使用select()获得了参数的个数,第二次使用select()作为print()函数的第二个参数,为了做到每次只输出一个值,我们又在select()的外面又打了一对小括号(
默然说话:你可以试着把
select()外面的那一对小括号去掉,看看会发生什么。)。看看测试结果:
> test_select("星期一","星期二","星期三","星期四","星期五","星期六")
1 星期一
2 星期二
3 星期三
4 星期四
5 星期五
6 星期六
第3章我们学习了for循环,我们可以利用for循环对数组进行遍历。也就是那些下标是数字的表,我们可以很容易的进行循环遍历,但我们要知道表是一个键—值对的形式,它并不止接受数字一种情形,另外,由于是键—值形式,所以我们也认为它们不是一个连续排序的数据,也就是无次序的数列,这种表我们可以叫它为散列表。for循环对这种无次序的数据也提供了处理的方法,这就是范型for循环。
范型for循环的语法与前面的for循环在语法上是有区别的:
for <变量列表> in <表达式> do
<循环体>
end
这个for循环的执行过程是这样的:
第一步:先计算表达式的值,这个表达式必须返回三个值:迭代函数,状态常量,控制变量。
第三步:将迭代函数的返回值依次赋值给in前面的变量列表。
> tbl={"苹果","梨"}
> for index,value in ipairs(tbl) do
>> print(index,value)
>> end
1 苹果
2 香蕉
3 梨
> tbl={
>> "苹果",
>> "香蕉",
>> "梨",
>> width=100,
>> height=100,
>> }
> for key,value in pairs(tbl) do
>> print(key,value)
>> end
1 苹果
2 香蕉
3 梨
height 100
width 100
> for key,value in pairs(tbl) do
>> tbl[key]=nil
>> end
--测试清除效果
> print(tbl[width])
nil
>> print(word)
>> end
这是
句子
表结构内置的table.sort()函数可以使用默认的方式对数字和字符串数据进行排序。如果你希望按照你的想法进行排序,那你可以把你的想法写成一个函数,然后传给table.sort(),它就会按照你的想法来完成排序。这个函数的思路,就是要告诉table.sort()排序时的两个数,哪一个更大些。
在这里我们要定义一些简单的数据以进行排序:
> guid={}
> table.insert(guid,{
>> name="默然的老婆",
>> class="牧师",
>> level=80,
>> })
> table.insert(guid,{
>> name="默然的儿子",
>> class="战士",
>> level=18,{
>> name="真默然",
>> class="猎人",
>> level=2,
>> })
在默认的情况下,我们会看到guid表中是按它们的插入顺序进行排序的:
> for key,value in pairs(guid) do
>> print(key,value.name)
>> end
1 默然的老婆
2 默然的儿子
3 真默然
> table.sort(guid)
attempt to compare two table values
stack traceback:
[C]: in function 'sort'
stdin:1: in main chunk
[C]: ?
所以,就需要我们来指究竟如何进行排序,也就是写一个比较函数,这个函数有两个参数,这两个参数就类似于我们表中的任意两个对象,我们在这个函数中来指明如何判断对象的大小,那么table.sort()就能知道如何对表进行排序:
> sortLevel=function(a,b)
>> return a.level<b.level
>> end
我们这里随意的指定了按对象的等级进行排序,a和b就是guid表中的任意两个对象,我们在sortLevel中对它们的level属性进行了比较,并返回了它们的比较结果,tabl.sort()就可以利用这个比较结果来完成排序,只要象下面这样写:
> table.sort(guid,sortLevel)
然后再次用for循环输出:
> for key,value.name)
>> end
1 真默然
2 默然的儿子
3 默然的老婆
我们看到,已经表中的对象已经改变了顺序。
本章主要介绍了变参函数,范型for循环以及对复杂数组的数据排序的概念。这些概念相对较高级,但是在设计和编写一个新插件时常常遇到。下一章我们将讨论Lua标准库,在这个库中我们将学习如何充分利用Lua提供给我们的帮助来完成我们想要进行的工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。