3

是否有/请建议一种语法来在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

我正在学习 lua,并且真的很难接受对 cur:fetch() 的重复调用。我看到重复/直到微不足道地解决了这个问题,但似乎我必须测试两次:

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

我认为在“row = ...”变得更复杂的情况下这种错误更容易发生,但似乎仍然不优雅。

4

3 回答 3

4

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

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

于 2014-10-20T13:09:27.437 回答
3

只需使用 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-20T13:07:58.027 回答
3

尝试

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