Wenn ich richtig verstehe, macht das, was du versuchst, nicht viel Sinn. uno
wird in der Umgebung nachgeschlagen, die heißt in, nicht mit. In Ihrem Beispiel ist es wie q(nil)
anrufen. Das Beispiel aus der anderen Frage funktioniert, weil sie in derselben globalen Umgebung arbeiten.
Sie können eine Hilfsfunktion verwenden schreiben Sie Ihre aktuelle Umgebungen nil
-lookups abzufangen, aber es muss präventiv in jeder Umgebung aufgerufen werden wollen Sie diese nil
-zu-- string
Lookups verwenden.
local function intercept (tab)
setfenv(2, setmetatable(tab or {}, {
__index = function (_, key)
return key
end
}))
end
Und Sie werden eine Umgebung benötigen Funktion Klonen, es sei denn, Sie möchten Ihre Sandkästen jedes Mal manuell erstellen, sonst werden Sie wahrscheinlich vermasseln Mutter Umgebungen (beispielsweise _G
). Sie könnten diese Logik innerhalb von intercept
für einen saubereren Funktionsaufruf verschieben, aber mit weniger Flexibilität.
local function clone_current_env()
local env = {}
for key, value in pairs(getfenv(2)) do
env[key] = value
end
return env
end
sie zusammen verwenden, können Sie nil
Lookups in verursachen Unabhängig davon, welche Umgebung sind Sie in Strings werden.
intercept(clone_current_env())
print(type(foo), type(bar)) --> string string
Dies ist einige hässlich metaprogramming, und ich weiß nicht wirklich, warum Sie Code wie folgt, es sei denn als Proof of Concept schreiben wollen würde.
Ein vollständiges Beispiel.
DEMO
local function clone (tab)
local new = {}
for key, value in pairs(tab) do
new[key] = value
end
return new
end
local function enable_nil_strings()
setfenv(2, setmetatable(clone(getfenv(2)), {
__index = function (env, key)
return key
end
}))
end
local function disable_nil_strings()
setmetatable(getfenv(2), nil)
end
-----------------------------------------------------
print(type(foo), type(bar)) --> nil nil
enable_nil_strings()
print(type(foo), type(bar)) --> string string
disable_nil_strings()
print(type(foo), type(bar)) --> nil nil
Schließlich wohl der beste Weg, dies zu realisieren wäre einfach um einen Ausführungskontext zu wickeln:
local function with_nil_strings (context, ...)
local env = {}
for key, value in pairs(getfenv(2)) do
env[key] = value
end
setfenv(
context,
setmetatable(env, {
__index = function (_, key) return key end
})
)
context(...)
end
print(type(foo)) --> nil
with_nil_strings(function()
print(type(foo)) --> string
end)
print(type(foo)) --> nil
starten durch vernünftige Variablennamen verwenden, Formatierung und weniger selbstinduzierte Indirektion. – Oka
@oka Ich habe einen Schnitt gemacht, der den Code so lesbar gemacht hat, wie ich es erkennen konnte. Sobald es global angewendet wird, sollte es viel einfacher zu lesen sein. – warspyking
@warspyking Ihre Bearbeitung hat eindeutige Konflikte mit dem Originalcode. Sie können das Original wie [this] (https://repl.it/EIW1) umschreiben, aber es ist immer noch unsinnig, da es versucht, Dinge in der falschen Reihenfolge zu suchen. Siehe meine Antwort unten. – Oka