“主要"在Lua中发挥作用? [英] "main" function in Lua?

查看:78
本文介绍了“主要"在Lua中发挥作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在python中,通常会定义一个main函数,以允许将该脚本用作模块(如果需要):

In python, one would usually define a main function, in order to allow the script to be used as module (if needed):

def main():
    print("Hello world")
    return 0

if __name__ == "__main__":
    sys.exit(main())

在Lua中,这样的习惯用法if __name__ == "__main__"是不可能的(也就是说,我认为不是).

In Lua, the idiom if __name__ == "__main__" isn't possible as such (that means, I don't think it is).

这是我通常要做的,以便在Lua中具有类似的行为:

That's what I'm usually doing in order to have a similar behaviour in Lua:

os.exit((function(args)
    print("Hello world")
    return 0
end)(arg))

...但是这种方法似乎重于括号":-)

... But this approach seems rather "heavy on parentheses" :-)

是否有更通用的方法(除了定义全局主函数外,这似乎是多余的)?

Is there a more common approach (besides defining a global main function, which seems redundant)?

推荐答案

没有做到这一点的适当"方法,因为Lua并不能真正区分代码的来源,它们只是函数.也就是说,这至少在Lua 5.1中似乎有效:

There's no "proper" way to do this, since Lua doesn't really distinguish code by where it came from, they are all just functions. That said, this at least seems to work in Lua 5.1:

matthew@silver:~$ cat hybrid.lua 
if pcall(getfenv, 4) then
    print("Library")
else
    print("Main file")
end
matthew@silver:~$ lua hybrid.lua 
Main file
matthew@silver:~$ lua -lhybrid
Library
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> ^C
matthew@silver:~$ lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> require "hybrid"
Library
> ^C
matthew@silver:~$

它通过检查堆栈深度是否大于3(标准Lua解释器中文件的正常深度)来工作.不过,该测试可能会在Lua版本之间中断,甚至在任何嵌入式/自定义Lua版本中也是如此.

It works by checking whether the stack depth is greater than 3 (the normal depth for a file in the stock Lua interpreter). This test may break between Lua versions though, and even in any embedded/custom Lua builds.

尽管它在启发式方法上取得了更大的飞跃,并且出现了失败案例(见下文),但我还将包括这种(稍微更便于移植)的替代方法:

I'll also include this (slightly more portable) alternative, although it's taking an even greater leap in heuristics, and has a failure case (see below):

matthew@silver:~$ cat hybrid2.lua 
function is_main(_arg, ...)
    local n_arg = _arg and #_arg or 0;
    if n_arg == select("#", ...) then
        for i=1,n_arg do
            if _arg[i] ~= select(i, ...) then
                print(_arg[i], "does not match", (select(i, ...)))
                return false;
            end
        end
        return true;
    end
    return false;
end

if is_main(arg, ...) then
    print("Main file");
else
    print("Library");
end
matthew@silver:~$ lua hybrid2.lua 
Main file
matthew@silver:~$ lua -lhybrid2
Library
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> ^C
matthew@silver:~$ lua 
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> require "hybrid2"
Library
>

通过将_G.arg的内容与'...'的内容进行比较来工作.在主要块中,它们将始终相同.在模块中,_G.arg仍将包含命令行参数,但是"..."将包含传递给require()的模块名称.考虑到您知道模块名称,我怀疑这对您来说是更好的解决方案.该代码中的错误在于用户执行带有1个参数的主脚本时,这是您模块的确切名称:

This one works by comparing the contents of _G.arg with the contents of '...'. In the main chunk they will always be the same. In a module _G.arg will still contain the command-line arguments, but '...' will contain the module name passed to require(). I suspect this is closer to the better solution for you, given that you know your module name. The bug in this code lies when the user executes the main script with 1 argument, and this is the exact name of your module:

matthew@silver:~$ lua -i hybrid2.lua hybrid2
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
Main file
> require "hybrid2"
Main file
> 

鉴于以上所述,我希望至少您知道自己的立场,即使这并非您的初衷:)

Given the above I hope at least you know where you stand, even if it isn't exactly what you had in mind :)

更新:对于适用于Lua 5.1和5.2的hybrid.lua版本,您可以将getfenv替换为debug.getlocal:

Update: For a version of hybrid.lua that works in Lua 5.1 and 5.2, you can replace getfenv with debug.getlocal:

if pcall(debug.getlocal, 4, 1) then
    print("Library")
else
    print("Main file")
end

这篇关于“主要"在Lua中发挥作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆