Lua学习之--函数,变长参数,closure(闭包)及select的一些特性

来源:互联网 发布:草木知春不久归全诗 编辑:程序博客网 时间:2024/05/17 22:30

原文链接:http://blog.csdn.net/huazhizui/article/details/7892479


1. Lua函数支持多返回值,但并不是每次调用函数返回的全部值都会被使用。

有一条规则是只有当函数调用是表达式最后一个元素时,才会使用它的全部返回值。看代码:

[plain] view plaincopy
  1. --string.find函数返回两个值,:被查找子串的开始索引和结束索引  
  2. s,e = string.find("Lua program language","Lua")  
  3. print(s,e)  --> 1    3  
  4.   
  5. --如果找不到,则输出nil和nil  
  6. s,e = string.find("Lua program language","Lub")  
  7. print(s,e)  -->nil   nil  
  8.   
  9.   
  10. --找出数组中最大的元素和其索引  
  11. function maximum(a)  
  12.     local mi = 1   --最大元素索引,开始假设第一个元素就是最大元素  
  13.     local m = a[mi]  
  14.     for i,val in ipairs(a) do  
  15.         if m < val then  
  16.             mi,m = i,val  
  17.         end  
  18.     end  
  19.     return mi,m  
  20. end  
  21.   
  22. print(maximum{1,2,10,4,5,7}) --> 3   10  
  23.   
  24. --返回多个值的函数只有作为表达式最有一个元素时才能使用它返回的多个值  
  25. --否则只取第一个值  
  26.   
  27.   
  28. --定义一个返回两个值的函数  
  29. function foo() return "a","b" end  
  30.   
  31. --foo()在表达式最后,使用了他返回的两个值  
  32. a,b = foo()  -->a    b  
  33. print(a,b)  
  34.   
  35. --foo()出现在表达式中间, 只使用了她返回的第一个值  
  36. a,b,c = foo(),"c"  
  37. print(a,b,c)   -->a  c   nil  
  38.   
  39. --使用了函数返回的两个结果  
  40. print(foo())  -->a   b  
  41.   
  42. --把函数调用放在括号中间, 迫使函数只返回的一个结果  
  43. print((foo()))  --> a  


2. 函数支持变长参数:... 

如果变长参数中没有nil,那么可以使用ipairs(...)来遍历得到所有的参数.

如果参数中有nil,那么就只能使用select()函数了. 因为ipairs只能遍历到nil处.

[plain] view plaincopy
  1. --变长参数  
  2.   
  3.   
  4. --使用变长参数完成对nunmber列表求和  
  5. function add(...)  
  6.     local sum = 0  
  7.     for i,v in ipairs(...) do  
  8.         sum = sum + v  
  9.     end  
  10.     return sum  
  11. end  
  12.   
  13. print(add{1.1,2.2,3.3,4.4,nil,6,8}) -->11   说明nil后面的6,8都没有遍历到  
  14.   
  15.   
  16. --如果变长参数中故意传入nil  
  17. --那么就要使用select函数来访问变长参数列表了.  
  18. --select得以参数如果传入的是整数n, 返回的是第i个元素开始到最后一个元素结束的列表  
  19. --如果传入的是"#",则返回参数列表的总长度  
  20.   
  21. function add2(...)  
  22.     local sum = 0  
  23.     local arg  
  24.     for i=1,select('#',...) do  
  25.   
  26.         --从输出结果可见,select(i,...)  返回的是第i个元素开始到最后一个元素结束的列表  
  27.         print(select(i,...))    -->2 4   6   nil 5   8  
  28.                                 -->4 6   nil 5   8  
  29.                                 -->6 nil 5   8  
  30.                                 -->nil   5   8  
  31.                                 -->5 8  
  32.                                 -->8  
  33.   
  34.         --只取列表的第一个值  
  35.         arg = select(i,...)  
  36.         if arg then  
  37.             sum = sum + arg  
  38.         end  
  39.   
  40.     end  
  41.     return sum  
  42. end  
  43. print(add2(2,4,6,nil,5,8)) -->25   说明nil后边的值都遍历到了  


3.closure(闭包)

我的理解是:使得内部函数能够调用外部函数的局部变量,而且在外部函数调用结束后仍然能使用外部函数的局部变量.而每次调用外部函数的会重新创建一个closure,而且以前的不会消失.这里不禁产生一个疑问:closure在什么时候释放?

[plain] view plaincopy
  1. -- closure的特性  
  2.   
  3. function newCounter()  
  4.     local i = 0  
  5.     return function()  
  6.         i = i + 1  
  7.         return i  
  8.     end  
  9. end  
  10.   
  11. c1 = newCounter()  --注意此处不是把newCounter函数赋给c1,而是把newCounter的返回值赋给c1,即 里面的c1是里面的匿名函数  
  12.   
  13. --此处newCounter只调用了一次, 所以创建了一个closure,所以i也只有一个,不管调用多少次c1,他们都访问的是同一个i;  
  14.   
  15. print(c1())  -->1  
  16. print(c1())  -->2  
  17.   
  18. c2 = newCounter()  -- 再次调用newCounter,将产生一个新的closure  
  19.   
  20. print(c2())  -->1  
  21. --此处c1的closure依然存在,  
  22. --疑问:每次调用函数都产生新的closure,那么closure什么时候释放?  
  23. print(c1())  -->3    
  24. print(c2())  -->2  

0 0
原创粉丝点击