接着上篇做的笔记,需要结合书来复习,本来准备两天通读这个近300页的pdf,现在看来我进度太慢了,前面阅读还挺快,到了这部分就 必须跟着书本写实例,才能明白基础概念。(某些用法还挺新奇的,默默感叹前辈的创造力)

11.深入函数-函数是一种“第一类值”
 lua中函数与其他传统类型的值(如数字,字符串)具有相同的权利,实际是持有某个函数的变量,
 可以存储在局部变量、全局变量,甚至table字段,有多种方式来操作这些变量。
 示例;
    a = {p=print}   
    a.p("hello word")   --相当于print("hello word")
    sin = math.sin
    a.p(sin(1))     --相当于print(math.sin(1)) ,调用正弦函数
    ppp = a.p
    ppp(10,20)      --相当于print(10,20)
 function foo(x) return 2*x end 相当于 foo = function (x) return 2*x end ,其中“function (x) return 2*x end ”
 被称为函数的构造式,就行table的构造式{}一样。函数构造式的结果称为匿名函数
 高阶函数:接受另一个函数作为实参的函数
    table.sort(table,匿名函数);接受一个table,并调用匿名函数对其中的元素进行排序

12. closure(闭合函数) 
一个closure就是一个函数加上该函数所需访问的所有“非局部的变量”,概念示例:
    function newCounter()
        local i = 0
        return function()
            i = i+1  --匿名函数访问一个“非局部的变量”i,
            --再次调用newCounter(),会创建一个新的局部变量i,从而得到新的closure
            return i
        end
    end 
    c1 = newCounter()
    c2 = newCounter()
    print(c1()) --结果为1
    print(c1()) --结果为2
    print(c2()) --结果为1,同一个函数,所创建不同的closure,拥有各自独立的局部变量i的实例
由于lua函数存储在普通变量中,所以closure可以重新定义某些函数
示例
    do
        local oldSin = math.sin  --保存在局部变量,只有新的sin可以访问得到,属于安全的运行环境
        math.sin = function(x)   --重新定义math.sin,并调用了原来的sin函数来完成计算
            retrun oldSin(x*math.pi/180)
            end
    end
针对示例中调用原来的oldSin函数,有点疑问,又写了一段,函数存储在普通变量中,不会再跟着函数的改动而改动
    function tmpfun(a,b)
            return a+b
    end
    oldfun = tmpfun
    print(oldfun(5,5))  --结果10
    tmpfun = function(a,b)
            return oldfun(a,b)*oldfun(a,b)
            end
    newfun = tmpfun
    print(newfun(5,5))  --结果100
    print(oldfun(5,5))  --结果10,也就是调用的还是旧版的tmpfun()

13. 非全局的函数(non-global function)
 存储在table中的函数,lua库常用的手段:如io.read,math.sin
 常规语法如下:
    lib = {}
    lib.foo = function(x,y) return x+y end
    lib.goo = function(x,y) retrun x-y end
 也可以用构造式
    lib = {
        foo = function(x,y) return x+y end
        goo = function(x,y) retrun x-y end
    }
 还可以这样
    lib = {}
    function lib.foo(x,y) return x+y end
    function lib.goo(x,y) retrun x-y end
 使用递归函数时需要注意要先定义局部变量函数
 尾调用是类似用goto的函数调用,一个函数是另一个函数的最后动作,该调用就是尾调用。
 示例;
    function f(x) return g(x) end 
    程序不需要保存任何关于该函数的栈信息,当g返回时,直接返回给调用f的地方,使尾调用时
    不占用栈空间,这种实现称为“尾调用消除”。

14.迭代器-一种可以遍历集合中所有元素的机制,在lua中的将迭代器表示函数,每调用一次函数,即返回集合中下一个元素
 简单示例;
    function values(t)  --简单的迭代器
            local i = 0
            return function()  i = i +1; return t[i]  end
    end
    t = {10,20,30}
    iter = valus(t)  --创建迭代器
    while true do
        local element = lter()  --调用迭代器
        if element == nil then
            break
        end
        print(element)
    end
 使用泛型for可以这么写,示例;
    function values(t)  --简单的迭代器
            local i = 0
            return function()  i = i +1; return t[i]  end
    end
    t = {10,20,30}
    for element in values(t) do  print(element) end --泛型for内部保存了迭代器函数,
                            --所以不需要lter变量,直到返回nil时结束循环
 高级应用,输入单词并遍历所有单词打印,示例:
    function allwords()
        local line = io.read() --输入的数据存放在table中
        local pos = 1
        return function()
            while line do
                local s,e = string.find(line,"%w+",pos) --找单词
                if s then --是否找到单词
                    pos = e + 1 --该单词的下一个位置
                    return string.sub(line,s,e) --返回该单词【迭代器的使用中,主要看返回值】
                else
                    line = io.read()
                    pos = 1
                end
            end
            return nil
        end
    end
    for word in allwords() do  --使用迭代器很简单
        print(word)
    end
15.泛型for -运行过程中实际保存三个值:迭代器函数,恒定状态,控制变量
 语法如下:
    for <var-list> in <exp-list> do
        <执行代码>
    end
    <var-list> 是一个或多个变量名的列表,逗号分隔
    <exp-list>是一个或多个表达式列表(通常为迭代器工程的调用),逗号分隔,
        表达式返回三个值供for保存:迭代器函数,恒定状态,控制变量,多余丢弃,不足补nil,
        如果第一个返回值为nil,那么循环终止。否则for执行循环体,随后再次调用迭代器函数,重复过程

16.无状态的迭代器-自身不保存任何状态的迭代器,避免创建新的closure开销