Luaリファレンス 要注意点 ~イタレータ~

イタレータとクロージャ

  • python 他と同じ。for in が対応していることも含めて標準的)
    function values (t)
        local i=0
        return function ()
            i=i+1
            return t[i]
        end
    end
    
    t = {10,20,30}
    
    for element in values(t) do
        print(element)
    end
    
    for element in values(t) do
        print(element)
    end
    
    このように2回繰り返しても、
    ちゃんとfor in 単位でクロージャがリセットされるので期待通りの挙動となる。

    以下のようにvtを用意してしまうと、当然変数寿命が維持されてしまい、
    上手く動かなくなるので注意
    t = {10,20,30}
    vt = values(t)
    
    for element in vt do
        print(element)
    end
    
    for element in vt do
        print(element)
    end
    

for i, v in func(a) の挙動

for i, v in func(a)

end

などとした場合、
forはイタレータを繰り返す道具として、ただ一度「func, a, 制御値(iへの初期値)」を要求し
func(a, 制御値)を繰り返す。
例えば、ipairsを以下のように実装した時、

function ipairs (a)
    return iter, a, 0
end

とリストを返すようにしておけば、
最初に、for ... in は iter(a, 0)を呼び出す。
そして、iter(a, 1)、iter(a, 2)と順に繰り返してゆく。

pairsも同様。

function pairs (t)
    return next, t, nil
end

next(t, k)を呼び出すと、1つ目の戻り値としてテーブルの次のキーが、2つ目の戻り値としてそのキーに関連付けられた値が返される。

これらは以下のように記述可能なことを意味する。

t = { a="ok", b="no" }
for k, v in next, t, nil do
    print(k, v)
end

さらに言えば、リストが不足している時は、nilで補われるという多重代入の法則を利用できるので、, nilを省略して、

t = { a="ok", b="no" }
for k, v in next, t do
    print(k, v)
end

と記載できる。

for ... in の展開

for var_1, ..., var_n in <explist> do <block> end は以下のように展開される。

Luaを深く使いこなすには、この展開内容を知っておく必要がある。
そうでなければ、見かけないくexplistが登場した際、その挙動を理解できないことがあるであろう。

do
    local _f, _s, _var = <explist>
    while true do
        local var_1, ..., var_n = _f(_s, _var)
        _var = var_1
        if _var == nil then break end
        <block>
    end
end

イテレータ関数が_f, 不変状態が_s, 制御変数の初期値がvarとすると、
制御変数は値 var_1=_f(_s, _var) var_2=_f(_s, var_1), ... var_n = _f(_s, var_n-1)のようになる。


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-01-24 (日) 14:31:54 (904d)