lua学习之迭代器与泛型 for 第三篇

迭代器与泛型 for 3

具备复杂状态的迭代器

  1. 使用 closure 能够保存迭代器所需保存的全部状态
  2. 也能够将迭代器所需的全部状态打包为一个 table 并保存在 恒定状态中
  3. 在循环过程当中 恒定状态 老是同一个 table
  4. 但这个 table 的内容却能够改变即在循环过程当中改变 table 数据
  5. 因为这种迭代器能够保存全部数据将其存储到 恒定状态中,所以第二个参数 控制变量 能够忽略
local iterator 
function allwords()
   local state = {line = io.read(), pos = 1}
   return iterator, state
end

function iterator(state)
	while state.line do -- 若为有效行的内容就进入循环
        -- 搜索下一个单词
        local s, e = string.find(state.line, "%w+", state.pos)
        if s then -- 找到一个单词
            state.pos = e + 1
            return string.sub(state.line, s, e)
        else -- 没有找到单词
            state.line = io.read() -- 尝试读取下一行
            state.pos = 1
        end
    end
    return nil
end

错误记录git

  1. 这里编码时犯了一个错误,没找到单词时使用的是函数定义 io.read ,而不是函数调用 io.read()
  2. 因此会报错 bad argument #1 to 'find' (string expected, got function)
  3. 意为第一个参数指望得到 string 类型,实际上获得的确实 function 类型
  4. 由于输入的第一行确定会有单词,因此不会进入 else 读取下一行
  5. 而打印出第一行的全部单词后,就不会尝试读取输入了,由于 string.find(state.line, ...) 其中的 第一个参数已经为 function 类型了,因此循环结束
  6. io.read() 用户输入任何东西都会为 string 类型
  7. 除非指定输入 io.read("*number") 这样就指定用户输入为 number 类型了

与无状态迭代器的对比

  1. 无状态迭代器将全部状态保存在 for 变量中
  2. 无需再开始一个循环时建立任何对象
  3. 基于 closure 实现的 table 比一个使用 table 的迭代器高效
  4. 由于访问 「非局部变量」要比访问 table

真正的迭代器

  1. 迭代器没有作实际的迭代,真正作迭代的是 for 循环
  2. 迭代器只是为每次迭代提供成功后的返回值
  3. 准确地称呼应为「生成器」

在迭代器中作实际的迭代操做

  1. 无需写循环
  2. 须要描述每次迭代时所需执行的动做或行为的参数,即参数为某个函数
  3. 迭代器接受一个函数做为参数,并在其内部循环中调用这个函数
function allwords(f)
    for line in io.read() do
        -- gmatch 匹配全部符合模式的字符串
        for word in string.gmatch(line, "%w+") do
            f(word)
        end
    end
end

allwords(print)
local count = 0
allwords(function(w)
	if w == "hello" then
        count = count + 1
    end
end
)
print(count)

local count = 0
for w in allwords() do
    if w == "hello" then
        count = count + 1
    end
end
print(count)

迭代器与生成器的对比

相同点

  1. 开销一致
  2. 每次迭代都有一次函数调用

不一样点

迭代器

  1. return 语句只能从匿名函数中返回
  2. 不能从作迭代的函数中返回

生成器

  1. 生成器容许两个或多个并行的迭代过程
    1. 逐个单词的比对两个文件,需同时遍历两个文件
  2. 且可在迭代体中使用 breakreturn 语句

本篇文章由一文多发平台ArtiPub自动发布
相关文章
相关标签/搜索