1. 1, 有状态迭代器  使用了闭包技术  
  2.    无状态迭代器  利用for循环保存状态  
  3.    多状态迭代器  利用tab保存了多个状态  
  4.    真正的迭代器  迭代器中遍历所有的元素,用传入的函数以迭代元素作为操作对象处理  
  5.  
  6.  
  7. 2, 函数与闭包  
  8.    函数的形式,当函数只有1个参数的时候,如果这个参数是字符串或者是{}的tab构造的时候,()调用符可以省略  
  9.    多返回值:总是调整函数返回值的个数适应环境  
  10.    x, y = foo2(), 20     --x=a,  y = 20 
  11.    x,y = foo0(), 20, 30  --x=nily = 20 
  12.    print(foo2(), 1)      --a 1  
  13.    print(foo2())         --a b  
  14.    b = {foo0(), foo2(), 4} -- b[1]=nil, b[2]=a, b[3]=4  
  15.      
  16.    使用()强制函数返回值为一个  
  17.    print((foo2()))  
  18.  
  19. 3,  unpack  
  20. function unpack(t, i)  
  21.     ii = i or 1  
  22.     if t[i] then  
  23.         return t[i],unpack(t,i+1)  
  24.     end  
  25. end  
  26.  
  27. function g(a, b, ...) end  
  28. call        params  
  29. g(3)        a=3b=nilarg={n=0}  
  30. g(3,4)      a=3b=4arg={n=0}  
  31. g(3,4,5,8)  a=3b=4arg={5, 8; n=2}  
  32.  
  33. 4, 选择参数  
  34.    local _,x = string.find(s, p)  
  35.    -- now use x  
  36.    function select(n, ...)  
  37.     return arg[n]  
  38.    end  
  39.  
  40. 5,  命名参数  
  41.     rename{old="temp.lua"new="tempX.lua"}  
  42.     function rename(arg)  
  43.         return os.rename(arg.old, arg.new)  
  44.     end    
  45.  
  46. 6, 闭包  
  47. 例1:  
  48. function newCounter()  
  49.     local i = 0 
  50.     return function()  
  51.         ii = i + 1  
  52.             return i  
  53.     end  
  54. end  
  55.  
  56. 例2:  
  57. function newCount()  
  58.     local i = 0 
  59.     function kcount()  
  60.         ii = i + 1  
  61.         return i  
  62.     end  
  63.     return kcount  
  64. end  
  65.  
  66. 例3:  
  67. do  
  68.     local oldsin = math.sin  
  69.     local k = math.pi/180  
  70.     math.sin = function (x)  
  71.         return oldsin(x*k)  
  72.     end  
  73. end  
  74.  
  75. 例4:  
  76. do  
  77.     local oldsin = math.sin  
  78.     local k = math.pi/180  
  79.     function math.sin(x)  
  80.         return oldsin(x*k)  
  81.     end  
  82. end  
  83.  
  84. 7, 递归调用  
  85. 形式1:  
  86. local fact  
  87. fact = function(n)  
  88.     if n == 0 then  
  89.         return 1  
  90.     else  
  91.         return n*fact(n-1)  
  92.     end  
  93. end  
  94.  
  95. 形式2:  
  96. local f, g  
  97. function g()  
  98.     f()  
  99. end  
  100.  
  101. function f()  
  102.     g()  
  103. end  
  104.  
  105. 8, 尾调用  
  106. function f(x)  
  107.     return g(x)  
  108. end  
  109. 由于g不需要f函数了,所以可以不再为f保留栈空间了  
  110. 支持不保存栈空间的方式,称为支持正确的尾调用  
  111. 下面写法是要保留栈的:  
  112. function f() g(x) return end --f要负责丢弃g的返回值  
  113. return g(x) + 1 --f要负责等g的返回值,并与1相加  
  114. return x or g(x) --f负责计算表达式的返回值  
  115. return (g(x))    --f负责计算表达式的返回值  
  116. 下面的写法是不保留栈的:  
  117. return x[i].foo(x[j] + a*b, i + j) --在调用之前会先计算表达式  
  118.  
  119. 9,lua中把chunk当做函数处理, 在chunk内可以声明局部变量的  
  120. 例子:  
  121. function f()  
  122.     function foo()  
  123.         print("test...")  
  124.     end  
  125. end  
  126. --直接执行foo()则显示错误, 因为还没有被定义, 如果要定义则必须运行函数f  
  127. --先执行f()然后再执行foo()则显示test...  
  128.  
  129. foo.lua  
  130. function foo()  
  131.     print("test...")  
  132. end  
  133. f = loadfile("foo.lua")后, foo被编译了,但还没有定义,如果要定义则必须运行chunk  
  134.  
  135. 10, loadstring 从字符串中读入chunk  
  136.     loadfile   从文件中读入chunk  
  137.     两个函数的返回值,当chunk中发生错误是,返回nil, 错误码  
  138.     两个函数总是在全局环境中编译它的串  
  139.       
  140. 11, error抛出异常, error抛出的异常不止可以是字符串,也可以是tab  
  141.     pcall捕获异常, 如果函数正常,则返回值, true, 返回列表....  
  142.                    函数捕获到了异常,则返回nil, 错误信息  
  143. 例:  
  144. function foo()  
  145.     error({code=1info="故意抛出的异常"})  
  146. end  
  147. local state, err = pcall(foo)  
  148. if not state then  
  149.     print(err.code, err.info)  
  150. end  
  151.  
  152. 12, assert(f(), errmsg)  检查f函数的第一个返回值,如果为nil,则抛出错误信息errmsg, 否则就返回f()的第一个参数  
  153.     assert(f())          检查f函数的第一个返回值,如果为nil,则抛出错误信息为f()的第2个返回值  
  154.       
  155. 13, 表明错误发生地儿  
  156. function foo (str)  
  157.     if type(str) ~= "string" then  
  158.         error("string expected")  
  159.     end   
  160. end  
  161.  
  162. foo({x=1}), 由于调用方式的错误,导致错误的发生,但是错误会定位在foo函数里面  
  163. 这种情况有时候让人分不清是调用问题,还是被调用函数的问题,为了表明问题发生的  
  164. 实际情况,可以用运行级别来表示;  
  165. 运行级别1,为你自己的运行级别  
  166. 运行级别2,则为你的被调用函数的运行级别  
  167. function foo (str)  
  168.     if type(str) ~= "string" then  
  169.         error("string expected", 2)  
  170.     end   
  171. end  
  172.  
  173. 14, print(package.loadlib()) 来判断是否能加载或者打开动态链接库  
  174.  
  175. 15, require   
  176.     require的两点功能  
  177.     1, require会搜索目录加载文件  
  178.     2, require会判断是否文件已经加载了  
  179.  
  180.     package.path里面的路径  
  181.     ?;?.lua;c:\wiindow\?;/usr/local/lua/?/?.lua  
  182.  
  183.     例如:  
  184.     require "world"  
  185.     package.loaded["world"]的值为true  
  186.  
  187. 16, 协作与线程  
  188. co = coroutine.create(function (param1, param2)  
  189.         for i0, 8 do  
  190.             print(i)  
  191.         end  
  192.         coroutine.yield(param1, param2)  
  193.         print("ok")  
  194.         return param1+2, param2+2  
  195. end)  
  196.  
  197. a, b, c = coroutine.resume(co, 1, 2) --等待代码执行完或者遇到yield  
  198. print("1:", a, b, c)  
  199. a, b, c = coroutine.resume(co)  
  200. print("2:", a, b, c)