2014-10-20 2 views
2

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

Рассмотрим этот сегмент из примеров 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 

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

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

я считаю это меньше ошибок в случае «строки = ...» становится все более сложным, но все еще кажется неэлегантным.

+2

'строки = CUR: выборка ({}, "а") и' строка = текущ: выборка (строка, "а") 'не точны дубликаты. –

+0

хороший улов, я не признал эту функцию эффективности на примере. – robm

ответ

4

Вы можете упростить первую петлю на это:

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

EDIT: sample page хитов в качестве возможного решения, используя iterators и цикл, как @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 

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

+0

Это похоже на форму повтора/до формы с другой инициализацией? он успешно устраняет один из вызовов cur: fetch(), но по-прежнему требует избыточного теста результата перед его использованием (печать в этом случае). – robm

+0

Вы правы. Обновлен мой ответ. – kikito

+0

Спасибо! Я попытался реализовать эквивалент секции итератора в образце, но не смог заставить его работать - ваш полный пример особенно полезен. Незначительная опечатка (s/cur/curr /) в строке 3 «вот как вы ее используете». – robm

3

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

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

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

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

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

+0

Попробовали несколько вариантов здесь и, как правило, пытались вызвать «значение таблицы» в строке «in/in»? – robm

3

Попытка

while true do 
    local row = cur:fetch ({}, "a") 
    if row then 
    print ... 
    else 
    break 
    end 
end 
+1

. Мое предпочтение было бы чем-то вроде 'while true do local row = cur: fetch ({}," a "), если не row, а затем break end' (извините, не может выработать форматирование многострочного кода в комментариях), но это еще не читаемость, на которую я надеялся, что – robm

+0

повторил бы второй раз, если бы мог, так как это с моей модификацией 1-строчного перерыва выше, на самом деле является формой, которую я использую в своем коде (из-за комментариев kikito о производительности). – robm