2012-07-08 128 views
3

我從Lua中的字符串創建函數(x)。我正在使用的代碼是從字符串創建Lua函數

function fcreate(fs) 
return assert(loadstring("return function (x) return " .. fs.." end"))() 
end 

這適用於全局變量,

u=fcreate("math.sin(x)") 

做對了。

但是,它似乎並不喜歡局部變量。所以

local c=1 
u=fcreate("math.sin(x)+c") 

不會工作,因爲c是本地的。

這是可以修復的嗎?

+0

爲什麼downvote? – 2013-06-03 01:15:33

回答

13

"loadstring does not compile with lexical scoping",所以不,看不到當地人撥打loadstring以外的地方。


這是可以解決的?

這取決於。爲什麼你首先使用loadtring? Lua支持閉包作爲第一類值,所以我不能從你的例子中看到爲什麼需要 loadstring。

你舉的例子:

u = fcreate("math.sin(x)+c") 

,而不需要被重寫爲loadstring或您的fcreate功能:

u = function(x) return math.sin(x)+c end 

這當然是一樣的:

function u(x) return math.sin(x) + c end 

我如果您擁有user-con,可以查看loadstring的情況你想編譯成一些其他功能的可模擬表達式,但你的案例與當地的c暗示情況並非如此。你是否想嘗試一些家庭式的lamda語法?

+8

我解決你的問題* *在第一線,連接你爲什麼你的代碼不能工作,你希望它的方式Lua的作者自己的解釋。然後,因爲我很好,想要有所幫助,我也試圖解決你的問題*(注意分隔兩部分的水平法則)。這後一部分主要是由猜測的,因爲你的問題的情況下/要求沒有說明,所以我貼一些額外的信息,並要求澄清您的要求,因此有可能進一步提供幫助。謝謝你的獎勵。 – Mud 2012-07-08 17:59:23

2

不能以任何合理的方式完成。對於爲什麼一個例子,看看這個:

function makefunction(name) 
    local a = 1 
    local b = 2 
    local c = 3 
    -- ... 
    return assert(loadstring("return " .. name)) 
end 

local a = 4 
local func = makefunction("a") 
print(func()) 

如果這個工作,什麼是印刷? 14?它是否從函數加載的地方捕獲變量,即使該函數不再存在?還是從它被稱爲的地方查找它?

第一個意思是該函數在詞彙的任何地方被創建。在函數退出後能夠訪問變量意味着該變量需要動態地升級爲upvalue,這不是Lua現在可以做的事情。現在,Lua可以在編譯過程中看到每個對局部變量的訪問權限,因此它知道哪些變量將變爲upvalues(在性能命中時)以及哪些變量保持爲當地變量。

第二個意思是說,在d函數內的變量訪問將與Lua中的所有其他訪問完全不同:Lua使用詞彙範圍而不是動態範圍。這在Lua中會有一個巨大的實施變化,而且是非常不一致的。

所以,無論是支持的。你可以控制一個動態加載函數的環境,使用Lua 5.1中的setfenv或Lua 5.2中的load(...)參數env,但這些都不允許你自動訪問局部變量。

1

的東西,如果你不需要變異的局部變量,你可以做的是通過這些值作爲參數傳遞給生成的函數。你仍然需要手動指定要關閉的變量,但它更好,然後什麼也不做。

例如,你可以建立你的閉合看起來像

return (function(a,b,c) 
    return function(x) return print(a, x) end 
end)(...) 

我們可以做的是通過改變你的函數看起來像

function fcreate(variables, fs) 

    local varnames = {} 
    local varvalues = {} 
    local nvars = 0 
    for n,v in pairs(variables) do 
    nvars = nvars + 1 
    table.insert(varnames, n) 
    table.insert(varvalues, v) 
    end 

    local chunk_str = (
    'return (function(' .. table.concat(varnames, ',') .. ') ' .. 
     'return function(x) return ' .. fs .. ' end ' .. 
     'end)(...)' 
) 

    return assert(loadstring(chunk_str))(unpack(varvalues, 1, nvars)) 

end 

local a = 1; 
local f = fcreate({a=a}, 'x+a') 
print(f(1), f(2))