2013-05-23 15 views
5

Es gibt zwei Skript-Dateien mit dem folgende Skriptlua: Modul Import in Bezug auf lokalen Bereich

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

    require "child" 
end 

//child.lua 
print(var) 

Auf diese Weise wird child.lua einen Nullwert drucken, da der Umfang in parent.lua nicht seine lokalen Merkmale aussetzt zum Modul. Ich dachte es würde, da die Require-Direktive in diesem Umfang und nach der Deklaration von Var. Mein Wunsch ist es, praktisch alle Linien des Kindes in den Elternteil zu injizieren. Das untergeordnete Skript wird nur zur besseren Lesbarkeit exportiert. Wie kann ich den lokalen Umfang weitergeben? Loadfile() hat nicht funktioniert, noch Dofile(). Die Funktionsumgebung fenv enthält keine lokalen Werte. debug.setlocal() scheint nicht in der Lage zu sein, neue Variablen zu erzeugen (auch würde es einen Empfänger im Kind erfordern). Gibt es eine Methode, außer das Skript neu zu kompilieren?

+0

Nein, das ist in Lua 5.1 nicht möglich. Es gibt einen Hack, der diesen Effekt in Lua 5.2 mit 'debug.upvaluejoin' erzeugen kann. – finnw

+2

Weder 'require' noch' dofile' ist dasselbe wie 'include', das es in Lua nicht gibt. – lhf

+0

Warum schreiben Sie nicht einfach Ihr Kindskript als eine Funktion, die Argumente empfängt? –

Antwort

1

Sie können mit ein wenig Aufwand. Wenn Ihre Variablen in child echte Upvalues ​​sind, können Sie sie mit Werten in Ihrer scope-Funktion "verknüpfen". Wenn es sich um globale Variablen handelt (was hier der Fall zu sein scheint), können Sie sie mithilfe von setfenv einer Umgebung zuordnen und diese Umgebung mit Werten aus Ihren lokalen Variablen füllen.

Im Folgenden wird abc drucken, wie man es erwarten würde (Sie loadstring-loadfile mit dem gleichen Effekt ändern):

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() 

Das alles für Lua 5.1 ist, aber es ist auch möglich, in Lua 5.2.