Reiterador II
 Versão «metatabela + corrotina» do artigo anterior:
 Versão «metatabela + corrotina» do artigo anterior:
local coroutine = coroutine
local math = math
local setmetatable = setmetatable
local table = table
local type = type
module "rand"
-- Criação da metatabela
local iter = { sec = {} }
iter.__index = iter
iter.__newindex = function (t, k, v)
    error("Chave " .. k .. " não encontrada")
end
-- Construtor local
function iter:new(o)
    o = o or {}
    setmetatable(o, self)
    return o
end
-- Método principal
function iter:next()
    local _, r = coroutine.resume(self.co)
    return r
end
-- Construtor público
function new(t)
    -- É preciso receber um vetor
    if type(t) ~= "table" then
        error "Parâmetro deve ser um vetor"
    end
    -- Vetor vazio?
    if table.getn(t) == 0 then
        error "Vetor vazio"
    end
    -- Criação da corrotina
    t.co = coroutine.create(function (t)
        -- Inicialição
        local m, e
        coroutine.yield(nil)
        -- Loop principal
        while true do
            m = table.getn(t)
            -- Se o vetor estiver vazio, começa de novo
            if m == 0 then
                while table.getn(t.sec) > 0 do
                    table.insert(t, table.remove(t.sec, 1))
                end
                m = table.getn(t)
            end
            -- Seleciona um elemento aleatoriamente
            e = table.remove(t, math.random(m))
            table.insert(t.sec, e)
            coroutine.yield(e)
        end
    end)
    -- Passa a tabela principal para a corrotina
    coroutine.resume(t.co, t)
    return iter:new(t)
end[]'s
 


 CC-BY: Os textos deste blog podem ser reporduzidos contanto que sejam informados autor e origem
 CC-BY: Os textos deste blog podem ser reporduzidos contanto que sejam informados autor e origem