LUA各知识点举例及详解.docx

上传人:b****2 文档编号:24396777 上传时间:2023-05-27 格式:DOCX 页数:11 大小:21.36KB
下载 相关 举报
LUA各知识点举例及详解.docx_第1页
第1页 / 共11页
LUA各知识点举例及详解.docx_第2页
第2页 / 共11页
LUA各知识点举例及详解.docx_第3页
第3页 / 共11页
LUA各知识点举例及详解.docx_第4页
第4页 / 共11页
LUA各知识点举例及详解.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

LUA各知识点举例及详解.docx

《LUA各知识点举例及详解.docx》由会员分享,可在线阅读,更多相关《LUA各知识点举例及详解.docx(11页珍藏版)》请在冰豆网上搜索。

LUA各知识点举例及详解.docx

LUA各知识点举例及详解

5.11 遍历表的数组部分

ipairs()允许您在不使用数值for循环的情况下遍历一个表的数组部分。

一些编程人员倾向于使用ipairs()而不是数值for循环,因为这样更简洁:

1.> tbl = {"alpha", "beta", "gamma"} 

2.> for idx,value in ipairs(tbl) do 

3.>> print(idx, value) 

4.>> end 

5.1, alpha 

6.2, beta 

7.3, gamma 

ipairs()函数接受一个表作为输入,返回遍历一个表的数组部分所需的所有信息,包括迭代器函数本身。

每一次迭代器函数的调用都返回一个元素的数值序号和这个元素本身。

这些变量可以按照您的期望任意命名,而且始终都在for循环的范围之内(即它们不能被这个范围之外的对象所访问)。

您可以通过在解释器里执行以下几个语句来更深入地了解ipairs()函数:

1.> print(ipairs(tbl)) 

2.function:

 0x300980, table:

 0x3072c0, 0 

3.> print(tbl) 

4.table:

 0x3072c0 

解释器会显示ipairs()所返回的一个迭代器函数、状态(在这里是您传递给它的表)和迭代器的初始值(0)。

这里没有什么深奥的东西,只是一组有用的函数。

5.12 遍历完整的表

另一个函数,pairs()允许您完整地遍历一个表,包括表的数组部分和散列表部分。

使用方法和ipairs()一样:

将表传入其中,并作为范型for循环的一部分来使用即可:

1.> tbl = {"alpha", "beta", ["one"] = "uno", ["two"] = "dos"} 

2.> for key,value in pairs(tbl) do 

3.>> print(key, value) 

4.>> end 

5.1, alpha 

6.2, beta 

7.one, uno 

8.two, dos 

使用pairs()函数遍历

在前面的样例中,pairs()函数好像是以元素添加的顺序来遍历的,但是这只是一个巧合。

在这个函数里遍历元素的顺序是不确定的,甚至是数值键也如此。

如果需要顺序地遍历表里的数值元素,就必须使用ipairs()函数,ipairs()可以保证顺序遍历。

pairs()函数的非顺序遍历由散列表的实现方式带来:

一个关联键/值(associatedkey/value)对的集合,没有内部顺序。

在使用pairs()函数的时候,您必须保证不添加元素。

这是因为pairs()调用了next()函数,在Lua5.1的参考手册中,对此函数有一些警告:

"在遍历中,如果您要对表中不存在的区域赋值,那么next()的行为是不确定的。

这样也许会修改已存在区域的值。

特别地,您也许会把已经赋值的区域清除掉。

"

这意味着若您在遍历的时候往表里添加元素,则next()也许没有反应,也可能更早地结束,或者会抛出一个错误。

在使用pairs()时,这一点必须牢记。

【责任编辑:

云霞 TEL:

(010)68476606】

 

5.13 表的清除

正如Lua5.1参考手册对next()函数所阐述的,您可以在遍历的过程里通过使用pairs()函数清除整个表。

下面的代码可以清除一个表里的所有元素:

1.for key,value in pairs(tbl) do 

2.    tbl[key] = nil 

3.end 

因为pairs()对于整个表的键都有作用,所以这是一个清除所有元素的捷径(如果您需要重新使用一个表)。

其他的迭代器

Lua里的许多其他函数都可以产生迭代器,这些迭代器也是非常有用的。

sring.gmatch()函数可以通过Lua模式匹配产生一个匹配string的迭代器。

在第6章里,您可以学习到更多关于这个函数和Lua模式匹配的信息,这里有一些样例:

for word in string.gmatch("These are some words", "%S+") do 

print(word) 

end 

These 

are 

some 

words 

for char in string.gmatch("Hello!

", ".") do 

print(char) 

end 

!

 

1.迭代器与Closure:

   在Lua中,迭代器通常为函数,每调用一次函数,即返回集合中的“下一个”元素。

每个迭代器都需要在每次成功调用之间保持一些状态,这样才能知道它所在的位置和下一次遍历时的位置。

从这一点看,Lua中closure机制为此问题提供了语言上的保障,见如下示例:

1functionvalues(t)

2locali=0

3returnfunction()

4i=i+1

5returnt[i]

6end

7end

8t={10,20,30}

9it=values(t)

10whiletruedo

11localelement=it()

12ifelement==nilthen

13break

14end

15print(element)

16end

17--另外一种基于foreach的调用方式(泛型for)

18t2={15,25,35}

19forelementinvalues(t2)do

20print(element)

21end

22--输出结果为:

23--10

24--20

25--30

26--15

27--25

28--35

   从上面的应用示例来看,相比于while方式,泛型for的方式提供了更清晰的实现逻辑。

因为Lua在其内部替我们保存了迭代器函数,并在每次迭代时调用该隐式的内部迭代器,直到迭代器返回nil时结束循环。

   2.泛型for的语义:

   上面示例中的迭代器有一个明显的缺点,即每次循环时都需要创建一个新的closure变量,否则第一次迭代成功后,再将该closure用于新的for循环时将会直接退出。

   这里我们还是先详细的讲解一下Lua中泛型(for)的机制,之后再给出一个无状态迭代器的例子,以便于我们的理解。

如果我们的迭代器实现为无状态迭代器,那么就不必为每一次的泛型(for)都重新声明一个新的迭代器变量了。

   泛型(for)的语法如下:

   forindo

      

   end

   为了便于理解,由于我们在实际应用中通常只是包含一个表达式(expr),因此简单起见,这里的说明将只是包含一个表达式,而不是表达式列表。

现在我们先给出表达式的原型和实例,如:

1functionipairs2(a)

2returniter,a,0

3end

   该函数返回3个值,第一个为实际的迭代器函数变量,第二个是一个恒定对象,这里我们可以理解为待遍历的容器,第三个变量是在调用iter()函数时为其传入的初始值。

   下面我们再看一下iter()函数的实现,如:

1localfunctioniter(a,i)

2i=i+1

3localv=a[i]

4ifvthen

5returni,v

6else

7returnnil,nil

8end

9end

   在迭代器函数iter()中返回了两个值,分别对应于table的key和value,其中key(返回的i)如果为nil,泛型(for)将会认为本次迭代已经结束。

下面我们先看一下实际用例,如:

1functionipairs2(a)

2returniter,a,0

3end

4

5

6localfunctioniter(a,i)

7i=i+1

8localv=a[i]

9ifvthen

10returni,v

11else

12returnnil,nil

13end

14end

15

16a={"one","two","three"}

17fork,vinipairs2(a)do

18print(k,v)

19end

20--输出结果为:

21--1one

22--2two

23--3three

   这个例子中的泛型(for)写法可以展开为下面的基于while循环的方式,如:

1localfunctioniter(a,i)

2i=i+1

3localv=a[i]

4ifvthen

5returni,v

6else

7returnnil,nil

8end

9end

10

11functionipairs2(a)

12returniter,a,0

13end

14

15a={"one","two","three"}

16do

17local_it,_s,_var=ipairs2(a)

18whiletruedo

19localvar_1,var_2=_it(_s,_var)

20_var=var_1

21if_var==nilthen--注意,这里只判断迭代器函数返回的第一个是否为nil。

22break

23end

24print(var_1,var_2)

25end

26end

27--输出结果同上。

    3.无状态迭代器的例子:

   这里的示例将实现遍历链表的迭代器。

1localfunctiongetnext(list,node)--迭代器函数。

2ifnotnodethen

3returnlist

4else

5returnnode.next

6end

7end

8

9functiontraverse(list)--泛型(for)的expression

10returngetnext,list,nil

11end

12

13--初始化链表中的数据。

14list=nil

15forlineinio.lines()do

16line={val=line,next=list}

17end

18

19--以泛型(for)的形式遍历链表。

20fornodeintraverse(list)do

21print(node.val)

22end

   这里使用的技巧是将链表的头结点作为恒定状态(traverse返回的第二个值),而将当前节点作为控制变量。

第一次调用迭代器函数getnext()时,node为nil,因此函数返回list作为第一个结点。

在后续调用中node不再为nil了,所以迭代器返回node.next,直到返回链表尾部的nil结点,此时泛型(for)将判断出迭代器的遍历已经结束。

   最后需要说明的是,traverse()函数和list变量可以反复的调用而无需再创建新的closure变量了。

这主要是因为迭代器函数(getnext)实现为无状态迭代器。

   4.具有复杂状态的迭代器:

   在上面介绍的迭代器实现中,迭代器需要保存许多状态,可是泛型(for)却只提供了恒定状态和控制变量用于状态的保存。

一个最简单的办法是使用closure。

当然我们还以将所有的信息封装到一个table中,并作为恒定状态对象传递给迭代器。

虽说恒定状态变量本身是恒定的,即在迭代过程中不会换成其它对象,但是该对象所包含的数据是否变化则完全取决于迭代器的实现。

就目前而言,由于table类型的恒定对象已经包含了所有迭代器依赖的信息,那么迭代器就完全可以忽略泛型(for)提供的第二个参数。

下面我们就给出一个这样的实例,见如下代码:

1localiterator

2functionallwords()

3localstate{line=io.read(),pos=1}

4returniterator,state

5end

6--iterator函数将是真正的迭代器

7functioniterator(state)

8whilestate.linedo

9locals,e=string.find(state.line,"%w+",state.pos)

10ifsthen

11state.pos=e+1

12returnstring.sub(state.line,s,e)

13else

14state.line=io.read()

15state.pos=1

16end

17end

18returnnil

19end

 2014/10/13

Lua中的虚变量——"_"

分类:

 Lua2013-11-0517:

57 395人阅读 评论

(1) 收藏 举报

lua虚变量

《ProgramminginLua》中有一段使用虚变量的代码,一些新手不太了解含义,这里讲解一下。

[html] viewplaincopy

1.一个典型的方法是使用虚变量(下划线)  

2.local _, x = string.find(s, p)  

3.-- now use 'x'  

4....  

Lua的函数可以具有多个返回值,比如下面的示例代码:

[html] viewplaincopy

1.print(string.find("example", "am"))  --- 输出 3 4  

string.find默认情况下返回两个值,即查找到的子串的起止下标,如果不存在匹配返回nil。

如果我们只想要string.find返回的第二个值,可以使用虚变量(即下划线)来存储丢弃不需要的数值。

[html] viewplaincopy

1.local _, s = string.find("example", "am")    

2.print(s)  ----- 输出 4  

总结来说,用一些不太会用到的名字命名一个回收箱变量,然后把不需要的值都丢到里面去,这种做法被称作虚拟变量法。

ps:

"_"就是一个变量,打印下就应该理解了

[html] viewplaincopy

1.print(_)  --输出3

学到现在发现一个有趣的事情,print可以这样用

print

(1)--1

print("1")--1

print(x)--nil

print("x")--x

5.2函数手册里面关于print的描述

print(···)

Receivesanynumberofargumentsandprintstheirvaluesto stdout,usingthe tostring functiontoconverteachargumenttoastring. print isnotintendedforformattedoutput,butonlyasaquickwaytoshowavalue,forinstancefordebugging.Forcompletecontrolovertheoutput,use string.format and io.write.

intendedfor用来…;目的在于

formattedadj.有格式的

instance例子,实例;情况;要求,建议;[法]诉讼手续

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 其它课程

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1