Lua base load()

作者: AlbertS | 来源:发表于2016-08-30 19:51 被阅读165次
    加载.png

    前言

    今天这个函数是一个非常非常危险的函数,我的电脑今天因为这个函数崩溃了两次,奇怪的是这个函数虽然在lua5.1的版本说明文档里,但是网上却几乎找不到关于它的任何用法。即使有个别的使用方法,在我的这个版本Lua5.1里也是运行不了的,提示语法错误。记过几番周折我终于试着写出了一种使用方式,但是我看不出他究竟有什么使用价值,我们还是一起来看一下吧。

    内容


    load

    • 原型:load(func [, chunkname])
    • 解释:使用参数func所指定的函数来加载程序块来获得程序片段,每一次调用函数func必须返回一个字符串,这个字符串连接了先前调用的结果,如果返回一个空串""nil、或者不返回值都标志着程序块的结束。
    • 如果没有错误函数会返回编译好的程序块作为一个函数,否则将会返回nil和错误信息,函数的运行环境是全局环境,参数chunkname通常被用来作为错误信息和调试信息使用,当省略时默认为"(load)" 。

    usage

    • 首先我们新建一个文件将文件命名为loadtest.lua然后编写代码如下:
    -- 用来计数调用次数
    local n = 0
    
    -- 用来作为可以影响的变量
    w = 0
    
    -- 被掉函数
    local function test(w)
    
        n = n + 1;
        print("test load function "..n.." times")
    
        if n > 10 then
            return nil
        else
            return "w = w + 1;"
        end
    end
    
    -- 输出被调函数
    print("\ntest function is", test, "\n")
    
    -- 运行load
    local retfunc = load(test, "use test")
    
    -- 输出结果函数
    print("\nretfunc function is", retfunc)
    
    -- 输出影响的变量
    print("\nbefore use function ret func, w = "..w)
    
    -- 调用结果函数
    retfunc()
    
    -- 输出影响的变量
    print("\nafter use function ret func, w = "..w)
    
    
    local function func_error()
        return "1+1"
    end
    
    print("\nsecond load", load(func_error, "use func_error"))
    
    
    • 运行结果
    base_load.png

    总结

    • 先说说这个函数为什么把我的电脑整崩溃了,原因是一开始不会用,在网上费了好长时间找了一个程序,写完代码测试——死循环了,一般的死循环沾满一个CPU,这个程序可倒好,4个CPU全是100%,导致电脑崩溃了。
    • 它出现死循环的原因就是由于他的结束条件,它会不断的调用函数func,知道它返回空串、nil或者是不返回,可是一般写好的函数,怎么会突然不返回,结果一直返回就死循环了。
    • 再说说返回值中代码块使用的变量w居然得是全局变量,否则编译不过去,我不知道这么做有什么意义。
    • 最后生成函数的代码里相当于有10句w = w +1;代码,由运行结果也证实了这一点。
    • 运行到最后我还是不明白这个函数究竟应该运用在什么场景下,请知道原因的大神们得我指点一下,谢谢了。

    相关文章

      网友评论

      • 9523_:#load (func [, chunkname])

        Loads a chunk using function func to get its pieces. Each call to func must return a string that concatenates with previous results. A return of an empty string, nil, or no value signals the end of the chunk.

        If there are no errors, returns the compiled chunk as a function; otherwise, returns nil plus the error message. The environment of the returned function is the global environment.

        chunkname is used as the chunk name for error messages and debug information. When absent, it defaults to "=(load)".

        看这个说明 load载入函数会执行返回结果 载入字符串每一次被调用 应该会把结果和上一次的返回值连接起来 作为函数体返回? 英文不大好 不知道对不对
        看了半天 我发觉我确实从未用过这个函数 貌似对什么代码中出现过这个也毫无印象 有点冷门的函数 我觉得应该是这样的用法
        function a(i)
        print(i)
        end

        b = load("a(1)")
        b()

        反射函数?
        9523_:@AlbertS 你打上断点 观察变量 就应该能看到实际上的值了
        9523_:@AlbertS 不是的,因该是引发了bug,它说明是成功返回 函数,nli 否则返回nil 错误信息 但实际上它返回的一个table load这个函数会吧_env作为upvalue传给指定的函数 函数为空时setupvalue就会失败,这个时候_env在栈顶并未被清除,所以返回的这玩儿其实就是_env环境对象的table 这是bug

        你换下5.2+试试 应该没问题 之前我试了一下的
        AlbertS:@9523_ 我也是看的这份文档,你的这个小例子因为函数a(i)没有返回任何字符串,所以函数b()的函数体是空的,也就是函数b()没有做任何操作,所以应该不是正确用法,不知道官方最初设计这个函数的目的是什么?
      • 9523_:额,这个其实很简单,是你没理解函数式编程的写法,转换一下我之前的那段代码
        num = [[
        local i = 0
        return function()
        i = i + 1
        return i
        end ]]

        读的是字符串 写法不一样 道理是一样的
        9523_:a=loadstring(num) 赋值啊 这个还不明白么 load不行
        干脆这样 你从简单的来

        a = loadstring("i = i + 1")
        i=0
        a()
        print(i)
        a()
        print(i)

        慢慢来 先从简单的理解起
        AlbertS:@9523_ 你这段代码到底怎才能用上load函数啊,如果直接封装成一个函数,使用load函数加载会出现死循环的……
        9523_:@9523_ 感觉这个应该只能loadstring,好久不用了有点生疏,呵呵,理解一下
        但原理是这样的 好像我这个写得不对 还要处理一下不然打出来的应该是function:000xxxxx这样的
        身边没lua解释器 手机敲代码不方便 你试下先
      • 9523_:你用的啥版本啊,这个函数现在还有?5.2+的版本已经取消这个函数了
        而且官方也推荐载入文件用loadfile载入字符串用loadstring,这个函数爹不疼妈不爱的,而且老版本中load函数还有一个严重的bug(lua史上最严重的BUG之一)

        我对你的代码看得不太明白,主要是不明白你想把这个函数用来做什么?计数器的话,这里用这个函数就不合适,这个函数的作用是装载的一段代码块,这个代码块可以被执行,当返回值为nil,就会输出第二个参数的错误错误信息(恩,这又有点像另一个函数的作用了,所以才说这个函数没啥用)

        你想写个计数器的话 可以这样 闭包的方式
        function num(i)
        return function ()
        i = i + 1
        return i
        end
        end

        a=num(1)
        print(a())
        print(a())
        print(a())
        print(a())
        print(a())
        print(a())
        试试吧,我觉得你想要实现的效果应该是这样,这样用循环控制也好,其它什么方式控制也好,都很方便,而且可以定义N个不同的计数器
        AlbertS:@9523_ 我必须再次说一下,我不会去用load函数去实现计数器,使用闭包的方法实现计数器我以前也确实写过,详情见http://www.jianshu.com/p/10e0cf2d84d2,我用的是5.1.4的版本,如果你以前用过load函数,请给我一个使用的例子,谢谢了
        9523_:@AlbertS 我知道你是51版,但是5.14和5.15这个函数应该是不一样的,515大概修复了这个bug吧;看出来了你打算用load去实现计数器,没有写出来只留了一个闭包是便于你理解哈 你代码的思路没错 只是用法上有问题 你把lua当中的一切赋值运算都理解为函数再来整理代码 应该就很容易理解了
        AlbertS:@9523_ @9523_ 谢谢你能抽出宝贵的时间给我写这么多回复,不过仔细看过你的回复之后我感觉你并没有仔细看过我写的文章。

        首先我在文章中多次提到了我用的是Lua5.1版本,并且写这个代码只是较劲脑汁才成功运行的一个例子,并没有实际意义,因为我发现网上的例子拿过来并不能执行,才决定自己写一个。

        这个例子仅仅是可以运行,但是并没有实际意义,这一点我在文章中也提到了。

        再有你说的load函数的BUG是不是指的是函数体为空时返回的并不是一个函数的问题,这个bug我也是了解过的,如果你指的是这个,我们有时间可以交流一下。

        另外,你说的计数器实现,使用闭包当然简单,这也是计数器常用的方式,我不会用load函数去实现计数器,只是想用这个例子抛砖引玉,看看他有什么其他的用法。

        最后再次感谢你给我的回复,和计数器实现的思路。

      本文标题:Lua base load()

      本文链接:https://www.haomeiwen.com/subject/uaqqettx.html