2017-06-28 24 views
3

ネストしたテーブルを横断できるイテレータを記述する必要があります。私はcoroutineを使って書きました。Lua - テールコール再帰へのコルーチンの再帰の書き換え

(パス、値)のペアの配列を作成しました。 {{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なしで同じ機能を取得しようとします。

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] 

しかし、私はまだ問題を抱えている:

-- 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 

このコードは、私が必要なものを返す私は、グローバル変数、poolを使用することはできません、このコードは、並列接続と呼ばれています。そして私はforサイクルから適切なテールコール再帰(return flatten(...))を1回だけ返すことができません。

私の質問:どのように私はこの機能を並行して呼び出すことができるものにパッケージ化するのですか?つまり、結果をグローバル変数にパイプするのではなく、戻り値で 'yield'パートが行うことを達成できますか?

パターンhereに従ったオブジェクトにしようとしましたが、動作できませんでした。

答えて

6

あなたは作ることができます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 
+1

コメントで答えに合うことができませんでしたか? ;) –

+0

@PaulKulchenko - はい、不幸です。 :-) –