Итераторы на Луа

Страницы: 1
RSS
Итераторы на Луа
 
Читаю книжку Иерусалимскиса про Луа.
Вот код оттуда.
Код
function values (t)
   local i = 0
   return function () i = i + 1; return t[i] end
end

t = {10, 20, 30}
iter = values(t) -- создает итератор
while true do
   local element = iter() -- вызывает итератор
   if element == nil then break end
   print(element)
end
Код работает как запланировано:


Почему всё становится плохо, если строку
Код
local element = iter() -- вызывает итератор
заменить на
Код
local element = values(t)

Чем отличаются эти варианты?
 
И раз уж пошла такая пьянка, второй вопрос оттуда же.
Код
function allwords ()
   local line = io.read() -- текущая строка
   local pos = 1 -- текущая позиция в строке
   return function () -- итерирующая функция
         while line do -- повторяет, пока есть строки
            local s, e = string.find(line, "%w+", pos)
            if s then -- слово найдено?
               pos = e + 1 -- следующая позиция после этого слова
               print(string.sub(line, s, e))
               return string.sub(line, s, e) -- возвращает это слово
            else
               line = io.read() -- слово не найдено; пробуетследующую строку
               pos = 1 -- перезапуск с первой позиции
            end
         end
   return nil -- строк больше нет; конец обхода
   end
end
Как эту функцию вызвать?
io.read считывает вводимый мною текст, и ничего не просиходит
 
У Вас values(t) возвращает функцию. Соответственно, Вы её и вызываете посредством iter().
Не помню, легален ли такой синтаксис, но попробуйте values(t)().
 
Т.е., проще говоря, присваивание iter = values(t) записывает в iter ссылку на функцию-итератор (генератор), и присваивание element = values(t) делает то же самое. А вот уже вызов этой функции даст вам следующий элемент таблицы-массива.
 
Вторую функцию вызывайте через allwords()() (соответственно, к предыдущему посту: values(t)() -- так можно). Сама функция возвращает функцию-генератор. Функция-генератор -- это такая функция, которая сохраняет некое состояние между её вызовами.

Код
function allwords ()
   local line = io.read() -- текущая строка
   local pos = 1 -- текущая позиция в строке
   return function () -- итерирующая функция
        while line do -- повторяет, пока есть строки
            local s, e = string.find(line, "%w+", pos)
            if s then -- слово найдено?
              pos = e + 1 -- следующая позиция после этого слова
              print(string.sub(line, s, e))
              return string.sub(line, s, e) -- возвращает это слово
            else
              line = io.read() -- слово не найдено; пробуетследующую строку
              if string.len(line) == 0 then 
                line = nil 
              end
              pos = 1 -- перезапуск с первой позиции
            end
         end
        return nil -- строк больше нет; конец обхода
   end
end

local fetch_next_word = allwords()
while fetch_next_word() do end

Этот код будет выводить Вам все слова из введённой строки, пока Вы не введёте пустую строку. Если не проверять на ввод пустой строки, то программа сама не завершится, т.к. пустая строка -- это всё ещё строка (т.е. не nil).
 
Цитата

Этот код будет выводить Вам все слова из введённой строки, пока Вы не введёте пустую строку. Если не проверять на ввод пустой строки, то программа сама не завершится, т.к. пустая строка -- это всё ещё строка (т.е. не nil).
Всё же оно чуть по другому работает.

дублирует одну строку. Если бы я как-то ухитрился ввести здесь 10 строк, он бы выдал 10 строк. Но не понятно как в этом окошке ввести ради тестов более чем 1 строку.
 
Enfernuz,
в первом коде
Код
local element = values(t)() 
со скобками в конце не является эквивалентом
Код
local element = iter()
потому что выводит до бесконечности
 
видимо, это как-то связано с тем, про что я сейчас читаю: замыкания, запоминание состояний...
 
Насчёт кода с allwords разобрался.
Вызывать надо так:
Код
for word in allwords() do
print(word)
end
 
Цитата
Let_it_go написал:
Enfernuz,
в первом коде
Код
   local  element  =  values(t)()   
со скобками в конце не является эквивалентом  
Код
   local  element  =  iter()  
потому что выводит до бесконечности

Верно, это не эквивалент. Т.е. так можно, но нужно ли - вопрос.
Мы же с Вами подобное уже обсуждали в предыдущей ветке: https://forum.quik.ru/messages/forum10/message35815/topic4169/#message35815
Страницы: 1
Читают тему
Наверх