[英]Lua - rewriting coroutine recursion to tail-call recursion
我必須編寫一個可以遍歷嵌套表的迭代器。 我用coroutine
寫了一個。
它創建了一個(路徑,值)對的數組,例如{{key1, key2, key3}, value}
意味着要獲得value
你必須做nested_table[key1][key2][key3]
。
在那之后我輕松地寫了find()
, findall()
, in()
,生活很明亮。
function table.extend(tbl, new_value)
local tbl = {table.unpack(tbl)}
table.insert(tbl, new_value)
return tbl
end
function iterate(tbl, parent)
local parent = parent or {}
if (type(tbl)=="table") then
for key, value in pairs(tbl) do
iterate(value, table.extend(parent, key))
end
end
coroutine.yield(parent, tbl)
end
function traverse(root)
return coroutine.wrap(iterate), root
end
然后我意識到我必須使用的Lua環境已經將coroutine
列入黑名單。 我們不能使用它。 所以我嘗試在沒有coroutine
情況下獲得相同的功能。
-- testdata
local pool = {}
test = {
['a'] = 1,
['b'] = {
['c'] = {2, 3},
['d'] = 'e'
}
}
-- tree traversal
function table.extend(tbl, element)
local copy = {table.unpack(tbl)}
table.insert(copy, element)
return copy
end
local function flatten(value, path)
path = path or {'root'}
pool[path] = value -- this is the 'yield'
if type(value) == 'table' then
for k,v in pairs(value) do
flatten(v, table.extend(path, k))
end
end
end
-- testing the traversal function
flatten(test)
for k, v in pairs(pool) do
if type(v) == 'table' then v = '[table]' end
print(table.concat(k, ' / ')..' -> '..v)
end
此代碼返回我需要的內容:
root -> [table]
root / b / c / 1 -> 2
root / b -> [table]
root / a -> 1
root / b / d -> e
root / b / c / 2 -> 3
root / b / c -> [table]
但我還是有一個問題:我不能使用全局變量pool
,這個代碼被稱為並行。 我不能從for
循環中進行正確的尾調用遞歸( return flatten(...)
),因為它只返回一次。
所以我的問題是:如何將此函數打包成可以並行調用的函數? 換句話說:我可以實現'yield'部分對返回值的作用,而不是將結果傳遞給全局變量嗎?
我試圖讓它成為一個對象,遵循這里的模式,但我無法讓它工作。
您可以將pool
變量設為本地:
test = {
['a'] = 1,
['b'] = {
['c'] = {2, 3},
['d'] = 'e'
}
}
-- tree traversal
function table.extend(tbl, element)
local copy = {table.unpack(tbl)}
table.insert(copy, element)
return copy
end
local function flatten(value, path, pool) -- third argument is the pool
path = path or {'root'}
pool = pool or {} -- initialize pool
pool[path] = value
if type(value) == 'table' then
for k,v in pairs(value) do
flatten(v, table.extend(path, k), pool) -- use pool in recursion
end
end
return pool -- return pool as function result
end
-- testing the traversal function
local pool = flatten(test)
for k, v in pairs(pool) do
if type(v) == 'table' then v = '[table]' end
print(table.concat(k, ' / ')..' -> '..v)
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.