2016-10-27 6 views
1

ルアでクォート関数を作成しようとしています。したがって、引数を文字列として使用できますが、引用符を使用せずに、またはいくつかの環境でそれらの引数にアクセスできます。多いのでthis questionルーアでの問題の解決

w = print 
function test() 
    local function _ix(_ , k) 
w("    _ix \\ " , _ , k) 
      local v = rawget(_G , k) 
w("    <-- " , k) 
     return k 
     end 
    local _ = setmetatable({} , { __index = _ix }) 
    local function q(_) return _ end 
     q = setfenv(q , _) 
return q 
end 

上の第二のコメント、私はそれを実行中のように:どのような私、そう

---------- Capture Output ---------- 

q(uno) nil 

> Terminated with exit code 0. 

q = test() 
w("q(uno)" , q(uno)) 

それも__indexのメタメソッドを呼び出すことはありません。間違ってる?

+5

スタート賢明な変数名を使用することでは、書式設定、および自己誘発間接指向性が低下します。 – Oka

+0

@oka私が作ることができるほどコードを読みやすく編集しました。一度それがグローバルに適用されると、はるかに読みやすくなります。 – warspyking

+0

@warspyking編集内容が元のコードと明確に矛盾しています。 [this](https://repl.it/EIW1)のようなオリジナルを書き直すことはできますが、間違った順序で物事を見ようとしている点でそれはまだ無意味です。下の私の答えを見てください。 – Oka

答えて

0

私が正しく理解していれば、やっていることはあまり意味がありません。 は、がと表示され、にはではなく、と表示される環境で検索されます。あなたの例では、q(nil)を呼び出すようなものです。他の質問の例は、同じ地球環境で働いているために機能します。

あなたの現在の環境nil -lookupsをインターセプトするヘルパー関数を書く使用することができますが、それはあなたがこれらのnilstring -to-検索を使用する任意の環境で先制呼び出さなければなりません。

local function intercept (tab) 
    setfenv(2, setmetatable(tab or {}, { 
     __index = function (_, key) 
      return key 
     end 
    })) 
end 

そして、あなたは手動であなたのサンドボックスごとに作成する場合を除き、機能を複製する環境が必要になります、それ以外のあなたよおそらく台無し親環境(例えば、_G)。このロジックをinterceptの内側に移動すると、より洗練された関数呼び出しが可能になりますが、柔軟性は低下します。それらを一緒に使用し

local function clone_current_env() 
    local env = {} 

    for key, value in pairs(getfenv(2)) do 
     env[key] = value 
    end 

    return env 
end 

、あなたは、文字列になることにしている方の環境でnil検索を引き起こす可能性があります。

intercept(clone_current_env()) 
print(type(foo), type(bar)) --> string string 

これは、いくつかの醜いメタプログラミングであり、私は本当にあなたが概念実証として以外に、このようなコードを書きたいと思いますなぜを知りません。


完全な例です。

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 

最後に、間違いなくこれを実施するための最良の方法は、単に実行コンテキストを包み込むように次のようになります。

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