Тест 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