最近犯了一个很蠢的错,Code Review 的时候觉得非常丢人,决心不再犯第二次了,同样的错误不再犯第二次,才能不断进步XD 于是写了个小工具来检查。但是实际跑起来,才发现 Lua 这里设计得不太好,留下了一个合法但很容易犯错的坑

具体错误非常简单,就是 for _,item in ipairs(seq) 写成了 for item in ipairs(seq)。而且由于 seq 里的值某些情况下会包含 1,2,3... 的序列,所以还不容易发现异常。花了一点时间写了个扫描器,主要还是调一个正则出来,扫描 for.*in ipairs 的用法。如果只用了第一个变量,那多半是写法有问题。通过这个扫描器,的确抓出了几处写错的地方

看完了所有异常警告,发现有些地方确实是用来做索引的,虽然很蠢但是结果上还是对的,有点蛋疼。明明 i=1,#seq 能够很好的代替 for i in ipairs(seq),只是写了后者也不能说写错了,很抓狂。中间还发现有人写了段很蠢的代码:

    local random_list = {}
    local table_insert = table.insert
    for i in ipairs(cfg) do
        table_insert(random_list, i)
    end
    local val = math.random(#random_list)

既然都用了 table_insert 代替 table.insert,说明对代码的速度还是有点追求的?那明明缓存一下 #cfg 就可以反复用了,为啥每次都创建一个临时 table…… 真是想不明白,看来只能靠团队约定了

语法设计上,ipairs 返回 index 和 val 应该是为了和 pairs 对称。但是允许了只访问 seq 的 index 这种写法,就容易滋生 bug,毕竟只要 index 的话用 i=1,#seq 就能做到,还能快得多。如果加 enumerate 呢,又觉得多增加了一个需要学习的特性,不雅观,设计真难。。