第七章 迭代器和泛型for

(坚决不做复读机,刻录机,写出自己的思考,略显蛋疼,这本书写的每句话都是步步推理,从基础以及原理一步步往后推导出之所以如此的原理,感觉不能删一句

由于看过了一遍,再看的时候,那么给自己抛出几个问题,带着问题,去学习思考,把前面章节的基础串起来,知晓并学习相关灵活应用。(暂时研究基础知识以及简单应用,有时间也要花时间攻研C底层代码)

  1. 迭代器和closure的关系
  2. 泛型for三元素,迭代器的工作机制

泛型for再循环过程内部保存了3个值:迭代器函数、恒定状态和一个控制变量。

这些基本的问题,必须弄清。

首先,现在看lua程序设计第二版,其实需要思考的是迭代器本身而不是for,迭代器本身就是函数。

迭代器

迭代器是一种可以遍历(iterate over)一种集合中所有元素的机制。在lua中,通常将迭代器表示位为函数。

原理:每个迭代器都需要在每次成功调用之间保持一些状态,这样才能知道他所在的位置及如何步进到下一个位置。closure对于这类任务提供了极佳的支持(一个closure可以访问其外部嵌套环境中的局部变量的函数)。

无状态的泛型for迭代器,实质上就是在一开始就声明了一个局部函数,用来做于闭合,然后根据for的特性,再写一个工厂函数,这样,外部缓存状态,工厂传入,闭合调用。为什么这么做呢,前面说过有状态的迭代器,如果要在工厂函数里面保存这些变量,如果不采用closure,当每次调用完的时候,引用解除,状态会丢失,然而采用closure,在closure内部会保持引用,这样当再次调用,会再次调用恒定值(此时就是upvalue的值)以及工厂中的局部变量(此时相当于控制变量),这样就做到有状态。那么既然有有状态,那么我们就来实现无状态的迭代器,避免每次调用都会生成新的闭合函数地址,那么谁有问题就解决谁,把闭合函数拿出来,单独声明一个局部函数,这些个状态,利用for迭代器的特性去做就OK。

泛型for

  1. 实际上它保存着3个值:一个迭代器函数、一个恒定状态(invariant state)和一个控制变量(control variable)
  2. 语法 for <var-list> in <exp-list> do <body> end。其中var-list是一个或多个变量名的列表,以逗号分割;<exp-list>是一个或多个表达式的列表,同样以逗号分隔。通常表达式列表只有一个元素,即一句对迭代器工厂的调用。
--for vart_1, ..., var_n in <exp-list> do <block> end
--等价于一下代码 ,可以用来理解泛型for的工作机制
do
    local _f, _s, _var = <exp-list>
    while true do
        local var_1, ..., var_n = _f(_s, _var)
        _var = _var_1
        if _var == nil then break end
        <block>
    end
end

如果迭代器无法套用for的模型,就应该尝试使用closur,本质原因有二:

  1. 创建一个closure就比传建一个table更廉价
  2. 访问“非局部的变量”比访问table字段跟快。

以后会看到另一种使用协同程序(coroutine)编写迭代器的方式,这种方式是功能最强的,但稍微有一点开销。

真正的迭代器

前面所说的迭代器这个名称多少有点误导的成分。因为迭代器并没有做实际的迭代,真正做迭代的是for循环。而迭代器芝士味每次迭代提供一些成功后的返回值。或许,更准确的应称其为“生成器(generator)”。不过“迭代器”这个名称已在其他语言中被广泛使用,例如Java。

“真正的迭代器”在老版本的lua中曾非常流行,那时雨涵还没有for语句。那他们比之生成器风格的迭代器又如何呢?这两种风格都有大致相同的开销,即每次迭代都有一次函数调用。编写真正的迭代器相对比较容易。不过,生成器风的的迭代器则更具灵活性。这种灵活性体现在两个方面:首先,它允许两个或多个并行的迭代过程;其次,它允许在迭代体中使用break和return语句。对于真正的迭代器来说,return语句只能从匿名函数中返回,儿并不能从被迭代的函数中返回。综上所述,我一般更喜爱生成器。(实际上我也的确因此喜欢)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值