Тест lua и назначение контроля внутри цикла

Есть ли / пожалуйста, предложите синтаксис для получения компактного "проверить и назначить" в lua?

Рассмотрим этот сегмент из примеров luasql ( http://keplerproject.org/luasql/examples.html).

-- retrieve a cursor
cur = assert (con:execute"SELECT name, email from people")
-- print all rows, the rows will be indexed by field names
row = cur:fetch ({}, "a")
while row do
  print(string.format("Name: %s, E-mail: %s", row.name, row.email))
  -- reusing the table of results
  row = cur:fetch (row, "a")
end

Я учу Луа, и действительно изо всех сил пытаюсь принять дублированный вызов cur:fetch(). Я вижу, что повторение / пока тривиально не решит проблему, но потом мне кажется, что я должен проверить дважды:

repeat
  row = cur:fetch ({}, "a")
  if row then
    print ...
  end
until nil == row

Я считаю, что это менее подвержено ошибкам в случае, когда 'row = ...' становится более сложным, но все же кажется не элегантным.

3 ответа

Решение

Вы можете упростить первый цикл до этого:

local row = {}
while row do
  row = cur:fetch(row, "a")
end

РЕДАКТИРОВАТЬ: образец страницы попадает в возможное решение с использованием итераторов и цикла for, как предлагает @doukremt. К сожалению, он также содержит пару ошибок (предполагается, что строки "распакованы" во втором примере, но не в первом, не объявляет все localи опускает больше скобок, чем в нормальном примере). Вот как вы можете преобразовать курсор в итераторе:

local iterate = function(cur)
  return function() return cur:fetch() end
end

Вот как вы используете это:

local cur = assert(con:execute("SELECT name, email from people"))

for row in iterate(cur) do
  print(string.format ("%s: %s", row.name, row.email))
end

Я должен предупредить вас, что итераторы в целом дороже, чем циклы while/repeat. Выполните тесты производительности, если вы беспокоитесь о скорости.

Просто используйте цикл for:

row = {}
for row  in cur:fetch(row, "a") do
    -- ...
end

Призыв к fetch() возвращает указатель на таблицу, которую вы передаете в качестве аргумента, так что вы также можете сделать:

row = {}
for foobar in cur:fetch(row, "a") ...

Важным моментом является то, что fetch() возвращает nil, когда строк больше нет, поэтому вам просто нужно проверить это, что неявно делает цикл for.

Пытаться

while true do
  local row = cur:fetch ({}, "a")
  if row then
    print ...
  else
    break
  end
end
Другие вопросы по тегам