在循环控制中进行Lua测试和赋值

有没有/请建议一种在lua中实现紧凑的“测试和赋值”的语法?

考虑来自luasql示例的以下部分(http://keplerproject.org/luasql/examples.html

-- 检索光标
cur = assert (con:execute"SELECT name, email from people")
-- 打印所有行,行将由字段名称索引
row = cur:fetch ({}, "a")
while row do
  print(string.format("Name: %s, E-mail: %s", row.name, row.email))
  -- 重新使用结果表
  row = cur:fetch (row, "a")
end

我正在学习lua,并且真的很难接受对cur:fetch()的重复调用。 我看到repeat / until毫不费力地解决了这个问题,但是然后似乎我必须测试两次:

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

对于“row = ...”变得更加复杂的情况,我认为这样做减少了出错的可能性,但仍然看起来不够优雅。

点赞
用户2002452
用户2002452

只需要使用 for 循环:

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

fetch() 的调用返回一个指针指向你传入作为参数的表格,所以你也可以这样做:

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

重要的一点是当没有更多的行时,fetch() 返回 nil,因此你只需要检查这个,而 for 循环会隐式地执行该操作。

2014-10-20 13:07:58
用户312586
用户312586

你可以将第一个循环简化为:

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

编辑:[示例页面](http://keplerproject.org/luasql/examples.html)指出使用[迭代器](http://www.lua.org/pil/7.1.html)和for循环的可能解决方案,就像@doukremt建议的那样。不幸的是,它还包含了一些错误(它假定在第二个示例中“解压缩”行,但是在第一个示例中没有声明一切“本地”,并省略了比在示例代码中理智的更多括号)。以下是如何将游标转换为迭代器:

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循环更昂贵。如果您担心速度,请执行性能测试。

2014-10-20 13:09:27
用户107090
用户107090

尝试

while true do
  local row = cur:fetch ({}, "a")
  if row then
    print ...
  else
    break
  end
end
2014-10-20 14:25:24