只有你足够强,别人才会和你讲道理。
文章: 280
浏览: 3,005,285
  • 博主:笨木头
  • 关注:Unity、Net Core、Blazor
  • 邮箱:musicvs@163.com
笨木头  2014-08-19 20:57     Cocos2d-x Lua     阅读(5043)     评论(2)
转载请注明,原文地址: http://www.benmutou.com/archives/1721
文章来源:笨木头与游戏开发
 

关于迭代器的内容, 还有一点点,不过已经无关紧要了,应该算是一种扩展吧,就一起来开开眼界好了~
笨木头花心贡献,哈?花心?不,是用心~

转载请注明,原文地址: http://www.benmutou.com/archives/1721

文章来源:笨木头与游戏开发

 
 

1.避免创建闭合函数

我们之前一直在说的迭代器,都是要创建闭合函数,但,大家有没有想过,有了恒定状态和控制变量之后,是不是就不需要闭合函数了?

先来回顾一下之前的迭代器函数:
[cce]
function dieDaiQi(t)
    local i = 0;
    return function(s, var) 
        i = i + 1;  
        
        if i > #t then
            return nil;
        end        
        return i, t[i];
    end, 10, 0
end
[/cce]
这是最后一次介绍的dieDaiQi函数,此时已经拥有了恒定状态和控制变量了。

不觉得那个local i变量很碍事吗?(小若:不觉得)

只要把它去掉,那就不存在闭合函数了。

 

我们把dieDaiQi函数改成这样子:
[cce]
function dieDaiQi(t)
    return function(s, var) 
        var = var + 1;
        if var > #s then
            return nil;
        end        
        return var, s[var];
    end, t, 0
end
[/cce]
我们把恒定状态改为t,控制变量初值仍然是0。

调用dieDaiQi函数后,返回一个新的函数,这个函数已经不属于闭合函数了。

于是,按照上一篇内容的介绍(不记得的就回头看看吧),每次调用函数时,参数s就是我们需要的table,参数var从0开始,代替了local i变量。

 

怎么样?稍微觉得恒定状态和控制变量有点用处了吧?

 

2.利用恒定状态创造更多变量

刚刚所说的方法,是挺好的,但是,能够改变的变量只有一个,如果这迭代器需要很多变量呢?

除了使用闭合函数之外,还有一个办法——将永恒变为善变。

 

我们继续修改dieDaiQi函数:
[cce]
function dieDaiQi(t)
    return function(s, var) 
        var = var + 1;
        if var > #s.list then
            return nil;
        end        
        s.money = s.money * s.money;
        print("呵呵,钱,对我来说,就是一个数字而已:" .. s.money);
        return var, s.list[var];
    end, {list = t, money = 10}, 0
end
[/cce]
留意一下,现在返回的恒定状态是一个table({list = t, money = 10})。

这个table在迭代过程中依旧是恒定不变的,但,它里面的内容可就不一定了。

试试调用这个迭代器吧:
[cce]
    local t = {"fdsd", "445", "9999"};
    
    for k, v in dieDaiQi(t) do
        print("k=" .. k .. ", v=" .. v);
    end
[/cce]
输出结果如下:

[LUA-print] 呵呵,钱,对我来说,就是一个数字而已:100 [LUA-print] k=1, v=fdsd [LUA-print] 呵呵,钱,对我来说,就是一个数字而已:10000 [LUA-print] k=2, v=445 [LUA-print] 呵呵,钱,对我来说,就是一个数字而已:100000000 [LUA-print] k=3, v=9999

 

怎么样?虽然每次迭代都是同一个table,但table的内容可是随时在变的。

就像某些人吖,嘴上说永远,行动却随时变。(小若:是说你自己吗?)

 

3.不需要for循环的迭代器

现在调用迭代器都是要用到for循环的,其实,在很久很久以前...有一个...(小若:停!我不是来听故事的)

好吧,其实,在以前,迭代器是不使用for语句的。

 

我们来模拟一下以前的做法:
[cce]
function dieDaiQiHistory(t, func)
    for i = 1, #t, 1 do
        func(i, t[i]);
    end
end
[/cce]
(小若:我噗,为什么一开始不这么做?这样多简单啊喂!)

咳咳,我们试试调用这个迭代器:
[cce]
    local t = {"fdsd", "445", "9999"};

  dieDaiQiHistory(t, function(k, v)   print("k=" .. k .. ", v=" .. v);   end); [/cce]
于是,在调用迭代器的时候,我们不需要使用for循环(虽然迭代器里面还是使用了)。

并且需要传递一个函数作为参数,用于回调,获得迭代的值。

 

由于我没有大量地使用者两种形式的迭代器,所以也没法去对比他们。

书上的作者是倾向于使用“现代”的迭代器。

 

而且我也发现,部分Lua的库函数,也是使用了这种形式的迭代,也许是历史原因,又也许是这种形式有其特有的使用场合。

 

4.结束

好了,关于迭代器,已经结束了。

感觉还不错,这是我第三遍翻这本书的前面章节了吧?果然还是得写写文章,才能理解地更透彻,印象也比较深刻。

越到后面就越难坚持了,加油吧...

(小若:所以说啊!为什么最后又用了省略号啊!用感叹号才显得比较有干劲啊...)

 

 

 

 

 
2 条评论
  • zheng 2018-05-24 08:27:08

    你好,请问下面的函数为什么就不是闭合函数?
    function dieDaiQi(t)
    return function(s, var)
    var = var + 1;
    if var > #s then
    return nil;
    end
    return var, s[var];
    end, t, 0
    end
    0回复
    • 博主 笨木头 2018-05-24 09:07:25

      为了回答这个问题,我又回头看了这几篇自己几年前的文章。

      按书上的描述,一个闭合函数就是:一个函数加上该函数所需访问的所有”非局部的变量“。
      你贴出的这个函数是没有【非局部变量】的,所以它已经不是闭合函数了。
      0回复
发表评论
粤ICP备16043700号

本博客基于 BlazorAnt Design Blazor 开发