我试图通过删除赋值来缩短代码,但是结果完全改变了,有什么解释吗?

问题描述

我尝试了此示例代码以查看其是否有效

--This example is from Programming in Lua Second Edition
function values (t)
  local i = 0
  
  return function () 
    i = i + 1 
    return t[i] 
  end
  
end
t = {10,20,30}
iter = values(t)
while true do
  local element = iter()
  -- calls the iterator
  if element == nil then 
    break 
  end
  
print(element) --> 10,30
end

我决定稍作更改,我认为代码将获得相同的结果,但我认为我错了

--This example is from Programming in Lua Second Edition
function values (t)
  local i = 0
  
  return function () 
    i = i + 1 
    return t[i] 
  end
  
end
t = {10,30}

while true do
  local element = values(t)()
  -- calls the iterator
  if element == nil then 
    break 
  end
  
print(element) --> This will print 10 forever if I don't stop the IDE
end

iter为什么那么重要?

解决方法

当您执行local element = values(t)()时,实际上是每次循环运行时都创建一个迭代器函数。记下您的values函数,看它有一个名为i的局部变量。每次运行此函数时,都会初始化局部变量并将其发送到处理迭代的内部函数。原始示例非常好,但是,如果您想练习局部变量和全局变量,则可以将local i更改为全局变量i或其他名称,然后将其移到函数外,这样每次运行迭代函数都不会被调用(您可以将其保持在本地,因此作用域将限于当前文件)。但是,完全不建议这样做,因为您的值可能会在一段时间后被另一个函数或文件重用,这也会使您每次运行只能进行一次完整的迭代(除非您将该值重新设置为零,然后再尝试进行迭代)。 )

local i = 0 -- Notice that the variable is taken out of the function.
-- With your example,the problem was that this variable was set to 0 for every
-- time you called the function.

function values (t)
  return function () 
    i = i + 1 
    return t[i] 
  end
  
end
t = {10,20,30}

while true do
  local element = values(t)()
  -- calls the iterator
  if element == nil then 
    break 
  end
  
print(element) --> This will print 10 forever if I don't stop the IDE
end

还要牢记性能,因为每次迭代示例时,垃圾回收都会创建,调用并销毁一个函数。这就是为什么原始示例仅创建一次迭代器函数,然后多次调用它,而您的示例在每次循环时都创建迭代器函数的原因。

如果您要做的只是遍历表中的元素,那么lua已经具有通用的for循环(对),请检查herehere。您的情况下的示例(这也会大大缩短您的代码):

local t = {10,30}

-- We don't need key in this case,but if you do,replace _ with k or
-- any other variable name you want.
for _,element in pairs(t) do
    print(element)
end