lua语言-《lua程序设计》6~7章函数和迭代器与泛型for

来源:互联网 发布:strstr 数组 编辑:程序博客网 时间:2024/06/15 02:02

接着上篇做的笔记,需要结合书来复习,本来准备两天通读这个近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.readmath.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)    end15.泛型for -运行过程中实际保存三个值:迭代器函数,恒定状态,控制变量 语法如下:    for <var-list> in <exp-list> do        <执行代码>    end    <var-list> 是一个或多个变量名的列表,逗号分隔    <exp-list>是一个或多个表达式列表(通常为迭代器工程的调用),逗号分隔,        表达式返回三个值供for保存:迭代器函数,恒定状态,控制变量,多余丢弃,不足补nil,        如果第一个返回值为nil,那么循环终止。否则for执行循环体,随后再次调用迭代器函数,重复过程16.无状态的迭代器-自身不保存任何状态的迭代器,避免创建新的closure开销