• LUA全总结


    ------------------------------------------------------------------------------
    --2018.7.21
    do --开启或关闭print
        xprint = print
        set_print = function(yes)
            print = yes and xprint or function()end
        end
        set_print(false)
    end
    
    do --第5章:函数
        --只有一个参数时: 字符串或表时,可以不写括号
        --将具有多个返回值的函数f1传入函数f2时,如作为f2最后一个参数,则f1所有返回值都会当作f2函数参数
        --否则,只有f1的第一个返回值被传入f2参数
        x = function()
            return 1, 2, 3, 4
        end
        print {1,2, 3}
        print "abcd"
        print(x()) --全部参数输出了 : 1 2 3 4 
        print("begin", x()) --全部参数输出了 : begin 1 2 3 4
        print(x(), " end") --输出结果:1 end
    
        --lua是将每个程序块(chunck)作为一个函数来处理的
        local fact--递归函数必须先声明
        fact = function(n) --递归函数必须先声明
            if n==0 then return 1 end
            return fact(n-1)*n
        end
    
        print(fact(4))
    
    
        --变长参数
        local xfunc = function( ... )
            local a1, a2 , a3 = ...
            print(a1, a2, a3)
        end
        xfunc(1, 3.2, "name")
    end
    do --第6章:闭包原理,upvalue,函数
        local names = {"Peter", "Paul", "Mary"}
        local grades = {Peter = 10, Paul = 7, Mary = 8}
        table.sort( names, function(n1, n2)
            return grades[n1] > grades[n2]
        end)
    
        for i=1, #names do
            print(names[i])
        end
        for i, v in ipairs(names) do
            print(names[i], v)
        end 
    
        --闭包,一个闭包就是函数加上其所需访问的“非局部变量”
        --闭包 = 函数 + upvalue
        --函数本身是一个特殊的闭包,其实LUA中没有函数,只有闭包
        --只所以能实现闭包,原因是【函数是第一类型值】
        --即函数是一个持续存在的变量,而不是传统的调用过程
        --传统的函数调用完后函数就出栈了
        --第一类型值的函数可以持续存在,因此它内部局部变量及“非局部变量”也就可以持续存在
        function newCounter()
            local i = 0
            return function( )
                i = i + 1
                return i
            end
        end
    
        local c1 = newCounter() --由于i被c1引用住了,因上newCounter这个【函数变量】调用完后没有释放
        print(c1()) --1
        print(c1()) --2
        local c2 = newCounter() --一个新的闭包
        print(c2()) --1
        print(c1()) --3
        print(c2()) --2
        print(c2()) --3
    
    end
    do --第7章:编写迭代器,闭包原理应用
        --------------------------------------------------
        --利用for in 范围模板实现一个自定义迭代器
        --1,ipair类型
        local old_ipairs = ipairs
        local ipairs = function(t)
            print("---------new-ipairs------------")
    
            local i = 0
            return function( )
                i = i + 1
                return  t[i] and i, t[i] --返回nil时,迭代结束
            end
        end
    
        local dat = {1, 2, 3, 10, 4, "hello"}
    
        --for后面的变量列表i, v是由迭代器函数的返回值决定的,个数不限
        for i, v in ipairs(dat) do --xpairs()函数只执行了一次
            print(i, v) --注意
        end
    
        --2,pair类型
        local old_pairs = pairs
        local pairs = function(t)
            print("---------new pairs------------")
            return next, t, nil --泛型for模板要求返回三个值:迭代器函数,数据表,控制器
        end
    
        local kvt = {
            a = 1,b = 2, c= 3
        }
    
    
        for k, v in pairs(kvt) do --k, v这两个变量接收的是next的返回值
            print(k, v)
        end
    end
    ------------------------------------------------------------------------------
    --2018.7.22
    do --debug.getinfo,栈层及upvalue
        local sumx = 0
        local  add = function(a, b) ----stack layer 1
            local info = debug.getinfo(3, 'nuS') --stack layer 0
            --输出
            --name add                        --函数名add
            --what lua                      --是一个lua调用
            --namewhat upvalue                 --函数被调用时,是一个upvalue类型的变量
            --numps 1                         --函数本身有一个upvalue类型变量sumx
            --short_src F:code	est1.lua
    
            --namewhat 用来说明函数类型,是global, local,field 还是upvalue
            --what 函数类型: lua, C, main
            --main是处于LUA文件最高层,即全局代码块,主块(main chunk)
            for k, v in pairs(info) do
                print(k, v)
            end
    
            --1,upvalue是一个变量
            --这里的sumx就是add的一个upvalue
            sumx = a + b 
            return a + b
        end
    
        local function oadd() --stack layer 2    
            --2,upvalue是一个函数
            --这里的add就是oadd的一个upvalue
            add(1,2)    
        end
    
        ----stack layer 3
        --处在这一层时,namewhat就是main
        oadd()
    end
    
    do --全局表,环境
        CSceneManager = {}
        for k, v in pairs(_G) do
            print(k, v)
        end
    
        set_print(true)
        local newEnv = {}
        local function fx( )
            --1,【函数环境】
            --开辟了一个全新的运行环境,它是一张表,后面的程序的视野被限定在了这个环境中
            --不能访问环境以外的东西【除非设置了元表】,也不可能对外界造成影响
            --环境的含义有2层:
            --1,程序在环境中运行,视野被限定在了环境内,见不到环境外的东西
            --2,程序在环境中运行,对环境产生改变,使环境产生了变量[函数也是],
            --程序运行结束后,外界可以通过环境来访问其中的变量
    
            --2,【环境元表,一个通往外部的通道】
            --带元表的环境就像一个:封装的环境+一个通往外界的通道
            setmetatable(newEnv, {__index = _G}) --设置环境通往外界的通道
    
            --3,【设置环境,函数环境】
            --设置新环境之前,记录下旧环境,以备恢复之用
            local env = getfenv()
            setfenv(1, newEnv)
            gx = 10             --等价于 newEnv.gx = 10
            newEnv.tx = 20         --等价于 tx = 20
        
            --4,【环境的私有变量】
            --注意:local声明的变量不属于环境,却可以被环境使用,在环境外不能被访问
            --因此,环境中的local变量就像是环境的私有变量,这是一个非常好的机制
            --模块本身是用环境机制来实现的,因此模块中的局部变量也相当于模块的私有变量
            local lgx = 123        --不是环境中的东西
    
            --5,【环境不能改变外界环境,局部变量可以】
            --此函数是local,因此是暂时性的对系统的print进行了覆盖
            --若不带local,则是新环境中的一个普通函数,不是对系统函数的覆盖
            local print = function(...) 
                xprint(">>", ...)
            end
    
            gx = lgx + 3
            print(gx)            --调用被覆盖的系统print
            setfenv(1, env)        --手动切换,恢复原来环境
    
            --使用环境名访问环境中产生的变量
            print(newEnv.gx, newEnv.tx, newEnv.lgx)     --10 20 nil
            print(gx, tx, lgx)    --nil nil 123
        end
        
        fx() --函数环境在函数结束后自动恢复为原来环境,也可以在函数中切换,如上
    
        --这里有点奇怪,newEnv.print不为nil
        print("after-newEnv:", newEnv.gx, newEnv.print, newEnv.lgx)
    end
    
    do --元方法,元表
        local ta = {1, 2, 3}
        local tb = {4, 5, 6}
        local mt = {
            __add = function(a, b) --相当于+号运算符重载
                local ret = {}
                for i=1, #a do
                    ret[i] = a[i] + b[i]        
                end
                return ret
            end,
    
            __eq = function(a, b) --重载 == 运算符
                for i=1, #a do
                    if a[i] ~= b[i] then
                        return false
                    end
                end
    
                mt.name = "hello"; --【错误】这时候mt还未定义完成,这里mt为nil
                return true
            end
            ,
    
            name = "rich",
            age = 30,
        }
    
        --设置元表相当于继承
        --元表相当于基类,这里t为子类
        mt.__index = function(t, k)
            return mt[k] --这里就可以用mt了
        end
        mt.__newindex = function(t, idx, val)
            --注意,这里必须用rawset,而不能用t[idx] = val,这会导致递归调用
            --因为t[idx] = val仍会触发 __nexindex调用
            rawset(t, idx, val)
        end
        mt.getname = function(self)
            return "namexxx"
        end
    
        --设置元表,
        --若子类中找不到某个变量时,就去调用基类的__index(tb, k)
        --注意:函数也是一个普通变量(第一类型值)
        setmetatable(tb, mt) --ta或tb任何一个实现了__add就可以
    
        --打印基类的所有变量,包括了函数
        for k, v in pairs(mt) do
            print(k, v)
        end
    
        local tc = ta + tb;
        for k, v in pairs(tc) do
            print(k, v)
        end
        print(ta == tb)
    
        --调用步骤:若子类中没有,则调用基类的__index方法
        print(tb.name)
        print(tb.__index(tb, "name")) --LUA的做法
        print(tb:getname())
    
        --rawget是在当前表中取,若不存在也不去基类中执行__index取得返回值
        --rawset是在当前表中对变量K设置,若K不存在也不去基类中执行__newindex
        --当对子类变量赋值时,若该变量不存在,LUA会去基类中找 __newindex
        tb.gender = 'male' --直接设置到tb中,而不是元表中
        print("-----------", tb.gender, mt.gender)
    
        --rawget(table, index)
        --注意rawget的第二个参数必须是字符串表示的key,因为lua会执行 table[index]
        print("rawget tb.gender", rawget(tb, "gender"))
    end
    
    print("-----------------------------------")
    do
    --通用问题:程序设计中用函数返回一个局部变量(对象)有什么问题
    --本质上讲,函数返回一个变量时,是对该变量进行了一次拷贝,将拷贝返回(匿名变量返回本身)
    --如果变量是基本数据类型,就没有问题,
    --如果变量是指针,也没有问题
    --如果变量是个对象,对象中有【堆指针】,就有问题
    --具体是:临时对象离开函数域后被析构,析构中必须释放指针指向的堆内存
    --这样,函数的接收者使用指针时就会崩溃,因为它指向的内存已经被释放了,指针非法了
    local func = function(t )
        local t1 = {a =1 , b =2 , c=3}
        return t1 --拷贝一个t1的副本交给接收者,也可以说接收者就是t1的直接拷贝
        --return {a = 1, b= 2, c = 3} --这就是匿名变量,直接将它返回给接收者,不拷贝
    end
    
    local t2 = func(t1)
    t2.a = 30
    print(t2.a)
    end
    -------------------------------------------------------------------------------
  • 相关阅读:
    Scala for the Impatients---(1)Basics
    2.2 Markov Chain
    2.1 Monte Carlo Integration
    1.2 Sampling From Non-standard Distribution
    1.1 Built-in Distributions In Matlab
    Design Pattern -- Builder
    Java Dynamic proxy
    The Difference Between Keypoints and Descriptors
    gcc -l option vs. -L option: The difference
    Stationarity and Independence of Data
  • 原文地址:https://www.cnblogs.com/timeObjserver/p/9391562.html
Copyright © 2020-2023  润新知