2016-03-21 67 views
2

我正在使用Lua表來存儲數據以創建網頁。正文內容存儲在一個表中,有一些靜態文本,一些由Lua函數生成。如何在包含函數的Lua表中使用table.concat

Web.HTML={ 
"<h1>Hello World</h1><br>", 
"<br><h2>Current Directory</h2><br>", 
io.popen("cd"):read('*l'), 
"<br><h2>Current Lua Interpreter</h2><br>", 
arg[-1] or arg[0], 
"<br><h2>Current Package Path</h2><br>", 
package.path:gsub(";",";<br>\n"), 
"<br><h2>Current Package CPath</h2><br>", 
package.cpath:gsub(";",";<br>\n"), 
"<br><h2>Current Environment Table:</h2><br>", 
io.popen("set"):read('*a'):gsub("\n","<br>\n").." ", 
"<br><h2>Current Date:</h2><br>", 
os.date(), 
"<br><h2>Math calculation</h2><br>", 
math.pi/180 
} 

該表,然後「印刷」使用table.concat功能,加入一些新行,以幫助可讀性:

print(table.concat(Web.HTML,"<br>\n")) 

如上預期在Lua 5.1或等效和服務器成功通過作品的示例這是我網頁的一部分。

我想在我的HTML表中放置任意的Lua代碼,它返回一個字符串連接,但我找不到正確的語法。 concat函數在'concat'的表中索引無效的值(函數)。

我曾嘗試:

Web.HTML = { 
"Classic text example:", 
function() print "Hello World"; end, 
} 

Web.HTML = { 
"Classic text example:", 
function() return "Hello World"; end, 
} 

一個更有用的例子是列出的Lua的全球環境中的所有表:

Web.HTML = { 
    "<br><h2>Current Lua Libraries</h2><br>", 
    function() 
     local text = '' 
     for i,v in pairs(_G) do 
      if type(v)=="table" then 
       text = text..i.."<br>\n" 
      end 
     end 
     return text 
    end 
    , 
    "Success!" 
} 

我也有嘗試使用loadstring(代碼;返回文本)()作爲一個熵在我的桌子上沒有成功。任何指針歡迎。

在此先感謝。

加文

回答

3

function明顯地返回一個函數。請立即撥打電話()。另外不要忘記將print更改爲return - 您的功能需要返回表格的值,而不是將其打印出來!

Web.HTML = { 
    "Classic text example:", 
    (function() return "Hello World"; end)(), 
} 

print(table.concat(Web.HTML,"<br>\n")) 
-- Classic text example:<br> 
-- Hello World 
+0

太好了,正是我想要的。謝謝G – Gavin

+1

對於大多數感興趣的函數返回一些統計信息,這不起作用:一個函數返回服務器正常運行時間,一個返回服務器生成的網頁數的函數。 'Web.HTML'對於同一類型的所有請求是相同的,不是嗎? –

+0

@EgorSkriptunoff,怎麼樣?如果您每次填寫新表並關閉當前值,則它將按預期工作。 –

2

table.concat不會自動地執行它遇到的代碼。它連接了一串字符串(或數字);這是它的工作。如果你傳遞一些不是字符串列表的東西,那麼你做錯了什麼。

如果你有一個字符串+ functions-that-return-strings的列表,那麼你需要將它轉換成你自己的字符串列表。這是很容易做到:

local list = --However you generate it. 
for i, val in ipairs(list) do 
    if(type(val) == "function") then 
    list[i] = val() --call function 
    end 
end 

然後你就可以連接listtable.concat。如果你想創建一個表的副本,而不是覆蓋現有的表,那麼也很容易。

local list = --However you generate it. 
local copy = {} 
for i, val in ipairs(list) do 
    if(type(val) == "function") then 
    copy[i] = val() --call function 
    else 
    copy[i] = val 
    end 
end 
0

table.concat將表格的元素連接到一個字符串。因此,它是 強制表中的每個元素可以轉換爲一個字符串。

在所有的嘗試:

Web.HTML = { 
"Classic text example:", 
function() print "Hello World"; end, 
} 

Web.HTML[2]是不能轉換爲字符串的函數。

在這種情況下,你可以用字符串或它們的返回值替換你的函數,方法是簡單地將它們定義在你的列表之外,然後在你的表構造函數中調用它們,或者用函數definitin在括號中立即調用它們,或者你可以重載表.concat滿足您的需求。雖然我寧願實現一個新的concat函數,而不是覆蓋標準函數以避免混淆。

0

不幸的是,標準功能table.concat()僅適用於字符串和數字。

您可以編寫自己的更靈活的table.concat

do 
    local orig_table_concat = table.concat 

    -- Define new function "table.concat" which overrides standard one 
    function table.concat(list, sep, i, j, ...) 
     -- Usual parameters are followed by a list of value converters 
     local first_conv_idx, converters, t = 4, {sep, i, j, ...}, {} 
     local conv_types = { 
     ['function'] = function(cnv, val) return cnv(val)  end, 
     table  = function(cnv, val) return cnv[val] or val end 
     } 
     if conv_types[type(sep)] then first_conv_idx, sep, i, j = 1 
     elseif conv_types[type(i)] then first_conv_idx,  i, j = 2 
     elseif conv_types[type(j)] then first_conv_idx,   j = 3 
     end 
     sep, i, j = sep or '', i or 1, j or #list 
     for k = i, j do 
     local v, idx = list[k], first_conv_idx 
     while conv_types[type(converters[idx])] do 
      v = conv_types[type(converters[idx])](converters[idx], v) 
      idx = idx + 1 
     end 
     t[k] = tostring(v) -- 'tostring' is always the final converter 
     end 
     return orig_table_concat(t, sep, i, j) 
    end 
end 

用法示例:

Web = {} 
Web.HTML = { 
    "Classic text example:", 
    function() return "Hello World"; end, 
} 

-- without converters 
print(table.concat(Web.HTML, "<br>\n")) 
--> Classic text example:<br> 
--> function: 0x9ad1398 

-- with a converter 
print(table.concat(
    -- usual parameters for table.concat: 
    Web.HTML, "<br>\n", 
    -- additional parameters (converters): 
    function(x) 
     if type(x) == 'function' then 
     return x() 
     else 
     return x 
     end 
    end 
)) 
--> Classic text example:<br> 
--> Hello World