第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但有一些差异。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还将帮助 支持 Lua 项目。
用 Lua 编程 | ||
第一部分。语言 第 7 章。迭代器和通用 for |
通常,迭代器需要保留比单个不变状态和控制变量更多的状态。最简单的解决方案是使用闭包。另一种解决方案是将所有需要的内容打包到一个表中,并使用此表作为迭代的不变状态。使用表,迭代器可以在循环中保留所需的数据。此外,它可以在进行时更改该数据。虽然状态始终是同一张表(因此是不变的),但表内容会在循环中发生变化。由于此类迭代器将所有数据都保存在状态中,因此它们通常会丢弃通用 for 提供的第二个参数(迭代器变量)。
作为此技术的示例,我们将重写迭代器 allwords
,它遍历当前输入文件中的所有单词。这一次,我们将使用具有两个字段(line
和 pos
)的表来保留其状态。
启动迭代的函数很简单。它必须返回迭代器函数和初始状态
local iterator -- to be defined later function allwords () local state = {line = io.read(), pos = 1} return iterator, state end
iterator
函数执行实际工作
function iterator (state) while state.line do -- repeat while there are lines -- search for next word local s, e = string.find(state.line, "%w+", state.pos) if s then -- found a word? -- update next position (after this word) state.pos = e + 1 return string.sub(state.line, s, e) else -- word not found state.line = io.read() -- try next line... state.pos = 1 -- ... from first position end end return nil -- no more lines: end loop end
只要有可能,你都应该尝试编写无状态迭代器,即那些将所有状态保存在 for 变量中的迭代器。使用它们时,你不会在开始循环时创建新对象。如果你无法将你的迭代放入该模型中,那么你应该尝试闭包。除了更优雅之外,闭包通常比使用表的迭代器更有效率:首先,创建闭包比创建表更便宜;其次,访问上值比访问表字段更快。稍后我们将看到另一种编写迭代器的方法,即协程。这是最强大的解决方案,但成本稍高。
版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 |