Iteradores são funções especiais criadas para iterar, ou seja, percorrer, listas, vetores (arrays), matrizes, tabelas ou o que quisermos. Nós criamos iteradores para usar na função for. Um exemplo de iterador que você já deve conhecer é o pairs. Vamos supor que eu tenha a seguinte tabela:
k = {1, 2, 3, 4, 5}E eu queira iterar por todos eles imprimindo o seu quadrado. Como faríamos isso? Casualmente, o código seria este:
for i = 1, 5 do
print(i ^ 2)
endMas e se eu quiser fazer isso várias vezes? Com uma lista que não segue um padrão? Então criamos um iterador, mas primeiro, vamos entender a estrutura de um em pseudocódigo Lua:
function iterator(values)
local pos = 0 --posição do iterador na lista
return function()
pos = pos + 1
if values[pos] ~= nil then
return values[pos]
end
return nil
end
endPerceba que eu não retorno um valor especifico ao chamar a função iterator(), eu retorno uma nova função. Essa função será chamada pelo for até que seu retorno seja nil, onde Lua assume que o iterador acabou. E como eu sei quando acaba? Simples, há uma variável (chamei, neste caso, de pos) que armazena a posição dentro do array values do próximo valor a ser retornado. A cada iteração, o valor aumenta em 1 dentro da função. Quando eu acessar um índice dentro do array que não existe, seu valor (values[pos]) será nil, portanto eu testo essa condição.
Parece bastante complexo, mas vamos voltar ao exemplo do quadrado. Chamarei minha função iteradora de square:
function square(numbers)
local pos = 0
return function()
pos = pos + 1
if values[pos] ~= nil then
return values[pos] ^ 2
end
return nil
end
endA cada chamada da função de retorno, eu aumento a posição e retorno este elemento elevado ao quadrado. Então, usarei a função assim:
for i in square(k) do
print(i)
endQue funciona como o esperado:
O que mais podemos fazer com iteradores? Podemos, por exemplo, bloquear uma palavra usando a função onTalk do xotservx:
local palavra = "jujuba"
function splitWords(phrase)
local pos = 0, words = phrase:gmatch("%w+")
return function()
pos = pos + 1
if words[pos] ~= nil then
return words[pos]
end
return nil
end
end
function onTalk(cid, type, text, position)
for w in splitWords(text) do
if w = palavra then
return false
end
end
return true
endClaro que esse exemplo é bastante simplório, mas demonstra a utilidade dos iteradores. Neste caso, eu testo todas as palavras que o player falou para encontrar uma palavra especifica que eu defini. Podemos transformar isso tudo em um loop while, para você entender um pouco melhor:
local words = splitWords(text)
while w = words() do
if w == nil then
break
end
if w = palavra then
return false
end
end
end
return trueUsando o iterador, ganhamos organização no código e o controle do for. Espero que façam bom uso de iteradores para organizar seus códigos