Lua的Iterator以及函數心得

來源:互聯網
上載者:User

from http://sunxiunan.com/?p=1249

local tbl = {"one", "two", "three", ‘five’}
local count = #tbl
local inc = 0

function Iter(tableinput)
return function()
if inc > count then
return
end
inc = inc + 1
return tableinput[inc], inc
end
end

for elem, index in Iter(tbl) do
print(elem)
if index > 2 then
inc = 0
end
end

如果運行一下的話,不出意外一定會死迴圈。如果把函數Iter改一下就是我們常見的generic for了。

function Iter(tableinput)
local count2 = #tbl
local inc2 = 0

return function()
if inc2 > count2 then
return
end
inc2 = inc2 + 1
return tableinput[inc2], inc2
end
end

跟蹤一下運行也可以發現,count2以及inc2這兩行在Iter被for調用的時候,只會第一次運行而且只運行一次。接下來的調用中只會從return function這裡開始。如果返回nil,那麼for就停止迴圈。

我比較好奇的是,對於Iter在for迴圈的時候,很顯然是保持了一個內部的堆棧不變,也就是說inc2和count2類似於c語言的static內部變數。但是學的還是一知半解,不知道如何dump出此時的堆棧狀態。

關於函數對於局部變數,好像是會在棧上做一個緩衝,看下面代碼

stringb = "bbbbbbbbbbbbbbb"
do
local internalA = "print for first time"
function printStrA()
print(internalA)
end
function printStrB()
print(stringb)
end
end

do
local internalA = "!!!!!!!!!!!!!!!!!!!!"
stringb = "cccccccccccccccc"
printStrA()
printStrB()
end

internalA = "!!!!2222222222222"
printStrA()
stringb = "ddddddddddddddddddd"
printStrB()

當我們運行這段代碼,可以發現

print for first time
cccccccccccccccc
print for first time
ddddddddddddddddddd

也就是對於printStrA,每次調用的結果都是一樣的,而printStrB的結果會根據全域變數stringb的不同而不同。這一點值得以後的研究。

關於閉包(closures),PIL上有一個很有意思的例子,我做了一些擴充。

local x = function ()
    local i = 0
    print "aaa"
    local function x2()
        i = i + 1
        print "bbb"
        return i
    end
    return x2 — 這個地方不能是return x2(),否則返回的就是值而不是函數
end

x()
print "======="
x()
print "======="

local c = x()
print "======="
print(c())
print "======="
print(c())
print "======="
print(c())
print "======="

local c = x()
print "======="
print(c())

結果會是什麼呢?

首先,很有意思的一點是,對於返回正確函數尾調用,一種情況下,return function()後面的代碼不會運行,就是說當x()時,以及當local c=x()的時候。

我們如果想達到計數器的效果,一定要用local c=x(),然後反覆調用c(),而不是調用x()。原因就是c實際上指向了x返回的匿名函數,這樣每次運行c,實際上啟動並執行就是那個匿名函數。另外一個有趣的結論是,對於返回正確尾調用的函數,尾調用實際上還沒有運行。

啟動並執行結果就是下面這樣,你猜對了嗎?

aaa
=======
aaa
=======
aaa
=======
bbb
1
=======
bbb
2
=======
bbb
3
=======
aaa
=======
bbb
1

關於尾調用, return g(x)是尾調用,而return (g(x))就不是,原因是return (Fun()) — This expression is a single function call surrounded in parentheses, which is different than the required single function call (the parentheses adjust Fun to one return value).

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.