为什么这不是一个有效的 table 迭代器?
Why isn't this a valid table iterator?
我在 lua 课上看到了这个例子:
function fromto(a, b)
return
function(state, seed)
if (seed >= state) then return nil
else return seed+1 end
end, b, a-1
end
它 returns 从 a 到 b 的后续整数值,包括在内。所以我尝试通过编写以下 table 迭代器来应用相同的逻辑:
function values(t) -- t is a table
return
function(state, seed)
return state[seed+1]
end, t, 0
end
它 returns 第一个值是正确的,但随后它抛出一个错误,提示我无法对字符串值 (seed
) 进行算术运算。但是 seed
接收的不是整数值 0
吗?发生了什么事?
因为第一个例子没有递增过程(比如a = a + 1
),我的想法是lua可能会在后台处理它......但如果没有,也许这是我困惑的原因。
seed
是迭代器函数第二个参数的错误名称。它实际上是控制变量。当你从 values
中 return 0 时,你 "seed" 它,但之后它的值在循环期间发生变化:它采用迭代器函数 returned 的第一个值。
您 return 从您的迭代器 (return state[seed+1]
) 中编辑了一个字符串,因此下次调用您的迭代器函数时,它会传递该字符串。你试图在上面做数学运算,然后......该死。
泛型for
接受三个参数:迭代器函数、不变状态和初始控制值。使用状态和控制值调用迭代器。迭代器然后 returns 下一个控制值,或 nil
表示迭代完成。
t = {"foo","bar","zip","zap"}
local function iteratorFunction (state, index)
index = index + 1
local val = state[index]
if val == nil then return nil end
return index, val
end
for k, v in iteratorFunction, t, 0 do
print(k,v)
end
所以第一次调用 iteratorFunction
接收 t
和 0
作为参数。对 iteratorFunction
的 下一个 调用获得 t
和 第一个值 return 来自 iteratorFunction
, 依此类推。
当你写一个像 values
这样的 "generator" 函数时,你只是 return 通用 for 循环所需的三个初始值,这样你的代码在使用该迭代器:
function values(t)
local function iteratorFunction (state, index)
index = index + 1
local val = state[index]
if val == nil then return nil end
return index, val
end
return iteratorFunction, t, 0 -- the same three values used in the for loop above
end
for k, v in values(t) do
print(k,v)
end
泛型 for
唯一需要的参数是迭代器函数。不变的状态和控制变量可以是 nil,如果你的迭代逻辑是在闭包中完成的,你可能会这样做:
function values(t)
local index = 0
-- our iterator function is a closure bound to `index` and `t`
local function iteratorFunction()
index = index + 1
local val = t[index]
if val == nil then return nil end
return index, val
end
return iteratorFunction, t, 0 -- the same three values used in the for loop above
end
for k, v in values(t) do
print(k,v)
end
如果您将 return index, val
更改为仅 return val
,values(t)
现在将仅迭代 t
中的值。之前我们不能这样做,因为我们需要 return 一个用于下一次循环迭代的控制变量。对于闭包,我们通过绑定到闭包的变量(又名 "upvalue")维护控制变量。
您可以使用另一种形式的带闭包的迭代器:
local function values(t)
local i = 0
return function()
i = i + 1
return t[i]
end
end
for x in values({1, 2, 3}) do
print(x)
end
1 2 3
迭代器会继续执行,直到 nil
被 return 编辑。无效的 table 字段(在 last 后面)始终为 nil,因此您只需要继续。
在您的示例中传递计数器值的表单使用 return 值来更新最后一个计数器值并且通常不使用。您使用字符串形式的 table 条目更新 seed
,因此下一次传递必须失败。
顺便说一句:您的 values 函数与 ipairs
.
的功能相同
我在 lua 课上看到了这个例子:
function fromto(a, b)
return
function(state, seed)
if (seed >= state) then return nil
else return seed+1 end
end, b, a-1
end
它 returns 从 a 到 b 的后续整数值,包括在内。所以我尝试通过编写以下 table 迭代器来应用相同的逻辑:
function values(t) -- t is a table
return
function(state, seed)
return state[seed+1]
end, t, 0
end
它 returns 第一个值是正确的,但随后它抛出一个错误,提示我无法对字符串值 (seed
) 进行算术运算。但是 seed
接收的不是整数值 0
吗?发生了什么事?
因为第一个例子没有递增过程(比如a = a + 1
),我的想法是lua可能会在后台处理它......但如果没有,也许这是我困惑的原因。
seed
是迭代器函数第二个参数的错误名称。它实际上是控制变量。当你从 values
中 return 0 时,你 "seed" 它,但之后它的值在循环期间发生变化:它采用迭代器函数 returned 的第一个值。
您 return 从您的迭代器 (return state[seed+1]
) 中编辑了一个字符串,因此下次调用您的迭代器函数时,它会传递该字符串。你试图在上面做数学运算,然后......该死。
泛型for
接受三个参数:迭代器函数、不变状态和初始控制值。使用状态和控制值调用迭代器。迭代器然后 returns 下一个控制值,或 nil
表示迭代完成。
t = {"foo","bar","zip","zap"}
local function iteratorFunction (state, index)
index = index + 1
local val = state[index]
if val == nil then return nil end
return index, val
end
for k, v in iteratorFunction, t, 0 do
print(k,v)
end
所以第一次调用 iteratorFunction
接收 t
和 0
作为参数。对 iteratorFunction
的 下一个 调用获得 t
和 第一个值 return 来自 iteratorFunction
, 依此类推。
当你写一个像 values
这样的 "generator" 函数时,你只是 return 通用 for 循环所需的三个初始值,这样你的代码在使用该迭代器:
function values(t)
local function iteratorFunction (state, index)
index = index + 1
local val = state[index]
if val == nil then return nil end
return index, val
end
return iteratorFunction, t, 0 -- the same three values used in the for loop above
end
for k, v in values(t) do
print(k,v)
end
泛型 for
唯一需要的参数是迭代器函数。不变的状态和控制变量可以是 nil,如果你的迭代逻辑是在闭包中完成的,你可能会这样做:
function values(t)
local index = 0
-- our iterator function is a closure bound to `index` and `t`
local function iteratorFunction()
index = index + 1
local val = t[index]
if val == nil then return nil end
return index, val
end
return iteratorFunction, t, 0 -- the same three values used in the for loop above
end
for k, v in values(t) do
print(k,v)
end
如果您将 return index, val
更改为仅 return val
,values(t)
现在将仅迭代 t
中的值。之前我们不能这样做,因为我们需要 return 一个用于下一次循环迭代的控制变量。对于闭包,我们通过绑定到闭包的变量(又名 "upvalue")维护控制变量。
您可以使用另一种形式的带闭包的迭代器:
local function values(t)
local i = 0
return function()
i = i + 1
return t[i]
end
end
for x in values({1, 2, 3}) do
print(x)
end
1 2 3
迭代器会继续执行,直到 nil
被 return 编辑。无效的 table 字段(在 last 后面)始终为 nil,因此您只需要继续。
在您的示例中传递计数器值的表单使用 return 值来更新最后一个计数器值并且通常不使用。您使用字符串形式的 table 条目更新 seed
,因此下一次传递必须失败。
顺便说一句:您的 values 函数与 ipairs
.