2013-05-23 8 views
5

次のスクリプトLUA:モジュールローカルスコープに関する輸入

//parent.lua 
function scope() 
    local var = "abc" 

    require "child" 
end 

//child.lua 
print(var) 

この方法で2つのスクリプト・ファイルがありますparent.lua内のスコープがローカル機能を公開していないため、child.luaがnil値を出力しますモジュールに接続します。 requireディレクティブはこのスコープ内で、varの宣言の後に記述されているので、私はそれを考えました。私の望みは実際には子供のすべてのラインを親に完全に注入することです。子スクリプトは読みやすくするために書き出されています。ローカルスコープにはどのように渡すことができますか? loadfile()はうまくいかず、dofile()もしませんでした。関数環境fenvはローカル値を保持しません。 debug.setlocal()は新しい変数を作成できないようです(子にもレシーバーが必要です)。スクリプトを再コンパイルする以外の方法はありますか?

+0

いいえ、これはLua 5.1では不可能です。 'debug.upvaluejoin'を使って、Lua 5.2でこの効果を与えることができるハックがあります。 – finnw

+2

'require'も' dofile'も 'include'と同じではありません。これはLuaには存在しません。 – lhf

+0

引数を受け取る関数として子スクリプトを書き直すのはなぜですか? –

答えて

1

少しでも努力できます。 childの変数が実際の上昇値である場合は、scope関数の値にそれらをリンクすることができます。それらがグローバル変数(ここではそうであるように思われる)の場合は、setfenvを使用してそれらを環境にマップし、その環境にローカル変数の値を設定します。

function vars(f) 
    local func = debug.getinfo(f, "f").func 
    local i = 1 
    local vars = {} 
    while true do 
    local name, value = debug.getlocal(f, i) 
    if not name then break end 
    if string.sub(name, 1, 1) ~= '(' then vars[name] = value end 
    i = i + 1 
    end 
    i = 1 
    while func do -- check for func as it may be nil for tail calls 
    local name, value = debug.getupvalue(func, i) 
    if not name then break end 
    vars[name] = value 
    i = i + 1 
    end 
    return vars 
end 

function parent() 
    local var = "abc" 

    local child = loadstring("print(var)") 

    local env = vars(2) -- grab all local/upvalues for the current function 
    -- use these values to populate new environment; map to _G for everything else 
    setmetatable(env, {__index = _G}) 
    setfenv(child, env) 

    child() 
end 

parent() 

これはLuaの5.1のすべてのですが、それはLuaの5.2にもできます:

あなたは(あなたが同じ効果でloadfileloadstringを変更することができます)期待通り、次はabcを印刷します。