到底如何终止for循环?

【背景】

泛型 for 在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量。

下面我们看看泛型 for 的执行过程:

1.首先,初始化,计算 in 后面表达式的值,表达式应该返回泛型 for 需要的三个值:迭代函数、状态常量、控制变量;与多值赋值一样,如果表达式返回的结果个数不足三个会自动用 nil 补足,多出部分会被忽略。

2.第二,将状态常量和控制变量作为参数调用迭代函数(注意:对于 for 结构来说,状态常量没有用处,仅仅在初始化时获取他的值并传递给迭代函数)。

3.第三,将迭代函数返回的值赋给变量列表。(k, v为变量列表)

4.第四,如果返回的第一个值为nil循环结束,否则执行循环体。

5.第五,回到第二步再次调用迭代函数

在Lua中我们常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素。Lua 的迭代器包含以下两种类型:

1.无状态的迭代器

2.多状态的迭代器

迭代器的状态包括被遍历的表(循环过程中不会改变的状态常量)和当前的索引下标(控制变量),ipairs 和迭代函数都很简单,我们在 Lua 中可以这样实现:

function iter (a, i)

    i = i + 1

     local v = a[i]

     if v then  --“if v”的意思是“当v为nil或false时该条件语句的判断为false,不执行分支语句”,但事实上,v可以为false,虽然当v为false时并不满足if v 这个条件——看附录。

           return i, v

     end

end


function ipairs (a)

     return iter, a, 0

end

当 Lua 调用 ipairs(a) 开始循环时,他获取三个值:迭代函数 iter、状态常量 a、控制变量初始值 0;然后 Lua 调用 iter(a,0) 返回 1, a[1](除非 a[1]=nil);第二次迭代调用 iter(a,1) 返回 2, a[2]……直到第一个 nil 元素

【正文】

关于泛型for循环,有两个需要注意的问题。

如果仔细思考,可以发现这两个问题都已经被我标注出来了,就是上方的粗体斜体字。

这两个问题是:

1.到底怎么样才会让for退出?

2.什么叫“每次调用该函数就返回集合的下一个元素”


这篇文章说第一个,用户到底要做什么才能退出泛型for循环。

先看下列代码

> a = {} --成功,不报错

> a['s'] = 12 --成功,不报错

> a[2] = 3 --成功,不报错

> a[a] = 2 --成功,不报错

> a[foo] = 56 -- table index is nil

于是我们得到第一个结论:lua并不支持用户将nil类型的值作为key使用

再看下列代码

> a = {1,2,3,4,nil,'tyt','rrp',nil,20,30,'xss'}

> for k,v in ipairs(a) do

>> print(k,v)

>> end

1      1

2      2

3      3

4      4

> for k,v in pairs(a) do

>> print(k,v)

>> end

1      1

2      2

3      3

4      4

6      tyt

7      rrp

9      20

10      30

11      xss

在这里,lua直接跳过为value为nil的键值对,但并没有报错;不仅没报错,甚至还为这些值为nil的键值对计算了key,导致key出现断层。

于是我们可以得到第二个结论:lua支持nil作为表的value

所以可见,更有可能是当key为nil时退出for循环,而不是当value为nil时退出(即所谓的“a[1]=nil”“直到第一个nil元素”)

下面来证实一下这个说法。

a = {1,2,3,4,5,6,7}

function iter (a, i)

    i = i + 1

    local v = a[i]

    if v then

          return i, nil

    end

end

function ipairs (a)

    return iter, a, 0

end

for k,v in ipairs(a) do

    print(k,v)

end

输出

1 nil

2 nil

3 nil

4 nil

5 nil

6 nil

7 nil

对比对照

a = {1,2,3,4,5,6,7}

function iter (a, i)

    i = i + 1

    local v = a[i]

    if v then

          return nil,v


    end

end

function ipairs (a)

    return iter, a, 0

end

for k,v in ipairs(a) do

    print(k,v)

end

输出

--无

综上,当迭代器给value返回了一个nil值时,for循环继续运行;当迭代器给key返回了一个nil值时,for循环退出

那么正常的ipairs是怎么工作的呢?

for循环写好后,lua会优先计算右边表达式的值:ipairs返回给for三个信息,iter函数、要被迭代的对象(状态常量)、下标(控制变量)。之后,for开始执行iter函数。

iter函数执行中,当lua处理到分支语句时

1.如果v为nil则条件判断为false,那么就不执行return语句,因此i的值就未被返回到k上去,结果k的值被设为nil,所以跳出循环。(有两种不同的操作可以使k为nil,大概的原理见延伸2)

2.如果v不是nil,也就是说v有具体的值,那么执行return语句。因为i一定是一个number类变量,所以for会一直执行、循环,直到v为nil时


延伸:

1.要想for运行,那么迭代器返回的第一个元素就至关重要——第二个、第三个、第n个元素都是可有可无的,但第一个元素必定不能为nil

2.在for循环体内更改k、v的值并不能造成for循环退出。根据lua手册的解释


“环变量 var_i 对于循环来说是一个局部变量; 你不可以在 for 循环结束后继续使用。 如果你需要保留这些值,那么就在循环跳出或结束前赋值到别的变量里去”

我认为每进行一次循环,都相当于做了一次“local k,v = iter(状态常量,控制变量)”的操作。在这个操作中,lua已经做完了对于k是否为nil值这个问题的检测操作——这是lua自动进行的,是和for关键字绑定在一起的,所以在循环体内更改k、v并没有什么影响。

也因此,当iter没有返回值时,k会变成nil,具体的原理见延伸4.

3.如何证明每次循环都会新建同名本地变量

原理:在同一作用域中,使用local关键字定义同名变量时,lua不会将原有变量设为nil——也就是说原有变量会保留其原来的值,不会变成新定义时赋予的值,也不会变为nil——但此时该原有变量已无法手动访问,除非闭包。而如果该原有变量没有外部引用来为它形成闭包的话,它会被回收。


collectgarbage("stop")

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

v = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

v = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

v = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

v = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

v = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

v = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

v = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

v = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,91,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8}

print(collectgarbage("count"))

end

collectgarbage("collect")

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k=nil

v=nil

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k=nil

v=nil

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k=nil

v=nil

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k=nil

v=nil

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k=nil

v=nil

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k=nil

v=nil

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k=nil

v=nil

print(collectgarbage("count"))

end

for k,v in ipairs({1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9}) do

k=nil

v=nil

print(collectgarbage("count"))

end

--[[

>lua -e "io.stdout:setvbuf 'no'" "定义全局变量和local定义变量肯定不是幂等的.lua"

41.6533203125

43.9951171875

46.3369140625

48.6787109375

51.0205078125

53.3623046875

55.7041015625

58.0458984375

60.3876953125

62.7294921875

65.0712890625

67.4130859375

69.7548828125

72.0966796875

74.4384765625

76.7802734375

79.1220703125

81.4638671875

83.8056640625

86.1474609375

88.4892578125

90.8310546875

93.1728515625

95.5146484375

97.8564453125

100.1982421875

102.541015625

104.8828125

107.22265625

109.5634765625

111.90625

114.244140625

116.5859375

118.92578125

121.2666015625

123.609375

126.5419921875

128.884765625

131.2265625

133.56640625

135.9072265625

138.25

140.5849609375

142.927734375

145.26953125

148.6103515625

150.953125

153.2919921875

155.634765625

157.9765625

160.31640625

162.6572265625

165

167.33203125

169.6728515625

172.015625

174.3544921875

176.697265625

179.0390625

181.37890625

183.7197265625

186.0625

188.3994140625

190.7421875

193.08203125

195.4228515625

197.765625

200.1044921875

202.447265625

204.7890625

207.12890625

209.4697265625

212.40625

214.744140625

217.0859375

219.42578125

221.7666015625

224.109375

226.4482421875

228.791015625

231.1328125

233.47265625

235.8134765625

238.15625

240.494140625

242.8359375

245.17578125

247.5166015625

249.859375

252.1982421875

254.541015625

256.8828125

259.22265625

261.5634765625

263.90625

266.244140625

268.5859375

270.92578125

273.2666015625

275.609375

277.9482421875

280.291015625

282.6328125

284.97265625

287.3134765625

289.65625

291.994140625

294.3359375

297.26953125

299.6103515625

301.953125

304.2919921875

306.634765625

308.9765625

311.31640625

313.6572265625

316

318.33203125

320.6728515625

323.015625

325.3544921875

327.697265625

330.0390625

332.37890625

334.7197265625

337.0625

339.3994140625

341.7421875

344.08203125

346.4228515625

348.765625

351.1044921875

353.447265625

355.7890625

358.12890625

360.4697265625

362.8125

365.1494140625

367.4921875

369.83203125

372.1728515625

374.515625

376.8544921875

379.197265625

382.1328125

384.47265625

386.8134765625

389.15625

391.494140625

393.8359375

396.17578125

398.5166015625

400.859375

403.1982421875

405.541015625

407.8828125

410.22265625

412.5634765625

414.90625

417.244140625

419.5859375

421.92578125

424.2666015625

426.609375

428.9482421875

431.291015625

433.6328125

435.97265625

438.3134765625

440.65625

442.994140625

445.3359375

447.67578125

450.0166015625

452.359375

454.6982421875

457.041015625

459.3828125

461.72265625

464.0634765625

467

469.33203125

471.6728515625

474.015625

476.3544921875

478.697265625

481.0390625

483.37890625

485.7197265625

488.0625

490.3994140625

492.7421875

495.08203125

497.4228515625

499.765625

502.1044921875

504.447265625

506.7890625

509.12890625

511.4697265625

513.8125

516.1494140625

518.4921875

520.83203125

523.1728515625

525.515625

527.8544921875

530.197265625

532.5390625

534.87890625

537.2197265625

539.5625

541.8994140625

544.2421875

546.58203125

548.9228515625

551.859375

554.1982421875

556.541015625

558.8828125

561.22265625

563.5634765625

565.90625

568.244140625

570.5859375

572.92578125

575.2666015625

577.609375

579.9482421875

582.291015625

584.6328125

586.97265625

589.3134765625

591.65625

593.994140625

596.3359375

598.67578125

601.0166015625

603.359375

605.6982421875

608.041015625

610.3828125

612.72265625

615.0634765625

617.40625

619.744140625

622.0859375

624.42578125

626.7666015625

629.109375

631.4482421875

633.791015625

636.7265625

639.06640625

641.4072265625

643.75

646.0849609375

648.427734375

650.76953125

653.1103515625

655.453125

657.7919921875

660.134765625

662.4765625

664.81640625

667.1572265625

669.5

671.833984375

674.17578125

676.5166015625

678.859375

681.1982421875

683.541015625

685.8828125

688.22265625

690.5634765625

692.90625

695.244140625

697.5859375

699.92578125

702.2666015625

704.609375

706.9482421875

709.291015625

711.6328125

713.97265625

716.3134765625

718.65625

38.1357421875

38.1650390625

38.1943359375

38.2236328125

38.2529296875

38.2822265625

38.3115234375

38.3408203125

38.3701171875

38.3994140625

38.4287109375

38.4580078125

38.4873046875

38.5166015625

38.5458984375

38.5751953125

38.6044921875

38.6337890625

38.6630859375

38.6923828125

38.7216796875

38.7509765625

38.7802734375

38.8095703125

38.8388671875

38.8681640625

38.8974609375

38.9267578125

38.9560546875

38.9853515625

39.0146484375

39.0439453125

39.0732421875

39.1025390625

39.1318359375

39.1611328125

39.7841796875

39.8134765625

39.8427734375

39.8720703125

39.9013671875

39.9306640625

39.9599609375

39.9892578125

40.0185546875

40.0478515625

40.0771484375

40.1064453125

40.1357421875

40.1650390625

40.1943359375

40.2236328125

40.2529296875

40.2822265625

40.3115234375

40.3408203125

40.3701171875

40.3994140625

40.4287109375

40.4580078125

40.4873046875

40.5166015625

40.5458984375

40.5751953125

40.6044921875

40.6337890625

40.6630859375

40.6923828125

40.7216796875

40.7509765625

40.7802734375

40.8095703125

41.4326171875

41.4619140625

41.4912109375

41.5205078125

41.5498046875

41.5791015625

41.6083984375

41.6376953125

41.6669921875

41.6962890625

41.7255859375

41.7548828125

41.7841796875

41.8134765625

41.8427734375

41.8720703125

41.9013671875

41.9306640625

41.9599609375

41.9892578125

42.0185546875

42.0478515625

42.0771484375

42.1064453125

42.1357421875

42.1650390625

42.1943359375

42.2236328125

42.2529296875

42.2822265625

42.3115234375

42.3408203125

42.3701171875

42.3994140625

42.4287109375

42.4580078125

43.0810546875

43.1103515625

43.1396484375

43.1689453125

43.1982421875

43.2275390625

43.2568359375

43.2861328125

43.3154296875

43.3447265625

43.3740234375

43.4033203125

43.4326171875

43.4619140625

43.4912109375

43.5205078125

43.5498046875

43.5791015625

43.6083984375

43.6376953125

43.6669921875

43.6962890625

43.7255859375

43.7548828125

43.7841796875

43.8134765625

43.8427734375

43.8720703125

43.9013671875

43.9306640625

43.9599609375

43.9892578125

44.0185546875

44.0478515625

44.0771484375

44.1064453125

44.7294921875

44.7587890625

44.7880859375

44.8173828125

44.8466796875

44.8759765625

44.9052734375

44.9345703125

44.9638671875

44.9931640625

45.0224609375

45.0517578125

45.0810546875

45.1103515625

45.1396484375

45.1689453125

45.1982421875

45.2275390625

45.2568359375

45.2861328125

45.3154296875

45.3447265625

45.3740234375

45.4033203125

45.4326171875

45.4619140625

45.4912109375

45.5205078125

45.5498046875

45.5791015625

45.6083984375

45.6376953125

45.6669921875

45.6962890625

45.7255859375

45.7548828125

46.3779296875

46.4072265625

46.4365234375

46.4658203125

46.4951171875

46.5244140625

46.5537109375

46.5830078125

46.6123046875

46.6416015625

46.6708984375

46.7001953125

46.7294921875

46.7587890625

46.7880859375

46.8173828125

46.8466796875

46.8759765625

46.9052734375

46.9345703125

46.9638671875

46.9931640625

47.0224609375

47.0517578125

47.0810546875

47.1103515625

47.1396484375

47.1689453125

47.1982421875

47.2275390625

47.2568359375

47.2861328125

47.3154296875

47.3447265625

47.3740234375

47.4033203125

48.0263671875

48.0556640625

48.0849609375

48.1142578125

48.1435546875

48.1728515625

48.2021484375

48.2314453125

48.2607421875

48.2900390625

48.3193359375

48.3486328125

48.3779296875

48.4072265625

48.4365234375

48.4658203125

48.4951171875

48.5244140625

48.5537109375

48.5830078125

48.6123046875

48.6416015625

48.6708984375

48.7001953125

48.7294921875

48.7587890625

48.7880859375

48.8173828125

48.8466796875

48.8759765625

48.9052734375

48.9345703125

48.9638671875

48.9931640625

49.0224609375

49.0517578125

49.6748046875

49.7041015625

49.7333984375

49.7626953125

49.7919921875

49.8212890625

49.8505859375

49.8798828125

49.9091796875

49.9384765625

49.9677734375

49.9970703125

50.0263671875

50.0556640625

50.0849609375

50.1142578125

50.1435546875

50.1728515625

50.2021484375

50.2314453125

50.2607421875

50.2900390625

50.3193359375

50.3486328125

50.3779296875

50.4072265625

50.4365234375

50.4658203125

50.4951171875

50.5244140625

50.5537109375

50.5830078125

50.6123046875

50.6416015625

50.6708984375

50.7001953125

>Exit code: 0

]]--

4.为什么没有返回值时k会是nil?换句话说,要怎么样才能让上个循环中变量的信息不会保留到下一个循环中去?

for循环对于其局部变量k、v的定义可能等价于“local k,v = iter(状态常量,控制变量)”,也可能等价于“local k;local v;k,v = iter(状态常量,控制变量)”。这两种写法最终得到的结果是一样的,但其中有一些值得关注的细节。

local x会强制创造一个叫做x的nil值。

第一种写法直接让k、v等于iter的返回值,第二种写法则是先为它们赋值为nil再分配返回值。

(当然,这两种写法也有其他的区别。lua在发现一个函数类型的变量时,会先找局部变量再找全局变量。这种写法上的差异会造成递归bug。)

而对于“接受返回值”这个行为,看下列代码

> function f()

>> end

> x = f()

> print(x)

nil

> print(f())

--空

> y = 12

> y = f()

> print(y)

nil

>

> function f()

>> return nil

>> end

> print(f())

nil

>

看起来这是一个奇怪的bug,print可以打印x(nil值),却无法打印f()(不返回任何值),但我们也可以这样理解:当且仅当语句是一个赋值表达式,且表达式的右边还是一个没有返回值的函数(或者返回值为空,比如光写一个return,没有任何参数)时,那么lua会自动为表达式左边的变量赋上nil值。

菜鸟教程:若变量个数 > 值的个数 ,则按变量个数补足nil

不过看下列代码:

> function a()

>> end

> function f(i)

>> i = i + 1

>> end

> function t(...)

>> local args = {...}

>> print(args[1],args[2])

>> end

> t(nil,nil)

nil    nil

> t(a(),a())

nil    nil

> f(a())

stdin:2: attempt to perform arithmetic on local 'i' (a nil value)

stack traceback:

        stdin:2: in function 'f'

        stdin:1: in main chunk

        [C]: ?

>

其实“赋值表达式”这个说法不准确,应该说是“发生赋值操作的语句”。

【附录】

> a = {false,false}

> for k,v in ipairs(a) do

>> print(k,v)

>> end

1      false

2      false

事实证明,只有为nil的value不会输出,为false的value仍然可以输出。

所以菜鸟教程上提供的这套迭代器实现原理是不准确的

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342