Is there / please suggest a syntax to achieve a compact 'test and assign' in lua?
Consider this segment from luasql examples ( 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
I am learning lua, and really struggling to accept the duplicated call to cur:fetch(). I see that repeat/until trivially fixes the issue, but then it seems I have to test twice:
repeat
row = cur:fetch ({}, "a")
if row then
print ...
end
until nil == row
I consider this less error prone for the case of 'row = ...' getting more complex, but still seems inelegant.
You can simplify the first loop to this:
local row = {}
while row do
row = cur:fetch(row, "a")
end
EDIT: The sample page hits at a possible solution using iterators and a for loop, like @doukremt is suggesting. Unfortunately it also contains a couple errors (it assumes that the rows get "unpacked" in the second example but not in the first, does not declare everything local, and omits more parenthesis than it's sane to in a sample code). Here's how you can transform a cursor in an iterator:
local iterate = function(cur)
return function() return cur:fetch() end
end
Here's how you use it:
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
I must warn you that iterators are in general more expensive than while/repeat loops. Execute performance tests if you are worried about speed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With