Lua supports your development of your own iterators - functions that can be used in a "for" loop.
The example shown below demonstrates how you can write an iterator that will take a string and iterate over it a line at a time. This particular iterator maintains an internal state (using the local "state" table). Inside this is a copy of the string we are iterating over, plus a position number, which is how far through the string we are.
The function getlines returns two things - the iterator function to be called for each iteration (declared locally to it), and the state variable, with the current position initialised to zero.
The example at the end shows how it might be used.
Output:
The example shown below demonstrates how you can write an iterator that will take a string and iterate over it a line at a time. This particular iterator maintains an internal state (using the local "state" table). Inside this is a copy of the string we are iterating over, plus a position number, which is how far through the string we are.
The function getlines returns two things - the iterator function to be called for each iteration (declared locally to it), and the state variable, with the current position initialised to zero.
The example at the end shows how it might be used.
-- getlines iterator - iterates over a string and returns one item per line
function getlines (s)
-- the for loop calls this for every iteration
-- returning nil terminates the loop
local function iterator (state)
if not state.pos then
return nil
end -- end of string, exit loop
local oldpos = state.pos + 1 -- step past previous newline
state.pos = string.find (state.s, "\n", oldpos) -- find next newline
if not state.pos then -- no more newlines, return rest of string
return string.sub (state.s, oldpos)
end -- no newline
return string.sub (state.s, oldpos, state.pos - 1)
end -- iterator
local state = { s = s, pos = 0 }
return iterator, state
end -- getlines
-- example
test = [[
every good
boy
deserves
fruit]]
for l in getlines (test) do
print ('"' .. l .. '"')
end -- for
Output:
"every good"
"boy"
"deserves "
"fruit"