從例子中學習閉包和正規化for

2021-07-28 06:04:17 字數 4378 閱讀 9610

又翻起了programming in lua這本書了,而且又看到 感謝貢獻之人這段**,今天就對這段**做下分析。**如下:

-- file: 'thanks.lua'

-- desc: to print the list of the contributing guys

function

list_iter

(t) local i = 0

local n = table.getn(t)

return

function

() i = i + 1

if i <= n then

return t[i] end

endend

helpful_guys =

for e in list_iter( helpful_guys ) do

print(e)

end

對於這段**,我們分兩個部分來講,第一部分是閉包,第二部分是正規化for的執行過程.

首先先講閉包,簡單一點說,閉包就是 乙個內部函式,它可以訪問乙個或多個外部函式的外部區域性變數

結構:包含兩個函式,乙個是閉包自己,乙個是工廠(建立閉包的函式)

-- 這裡list_iter函式是建立閉包的工廠

function

list_iter

( t )

local i = 0

local n = table.getn( t )

-- 匿名函式,list_iter函式的返回值

return

function

() -- 變數i、n和t相對於這個匿名函式,是個外部函式(list_iter)的區域性變數

i = i + 1

if i <= n then

return t[i] end

endend

ffunc = list_iter(  )

執行list_iter的返回值就是乙個函式, 它儲存了三個值,i=0, n=2, t=

第一次執行ffunc函式, 即

print( ffunc() )
輸出結果為 a

因為 ffunc 它是乙個函式,執行的時候

i=i+1 這時i=0+1=1

t[1] 就是 a

執行完之後,這個ffunc的儲存的 外部的區域性變數i變成了1

同理再執行一下 ffunc時,

輸出的結果為 b

同時,這個ffunc的儲存的 外部的區域性變數i變成了2

這時候再執行一下的時候,結果就是nil, 因為

i=2+1 等於 3

i<=n不成立了(3<=2不成立)

所以接下來執行的時候,結果都是為nil,

但是每執行一次的時候,ffunc這個閉包的區域性變數i就會加1

function

iter_list

( t )

local i = 0

local n = table.getn(t)

return

function

() i = i + 1

print( "i=", i )

if i<= n then

return t[i]

endendend

ffunc = iter_list( )

print( ffunc() )

print( ffunc() )

print( ffunc() )

print( ffunc() )

執行結果:

接下來講一下正規化for的執行過程

其語法如下

for

in do

end

其中

var-list 是乙個或多個以逗號分割的變數名列表

exp-list 是乙個或多個以逗號分割的表示式列表,迭代函式(閉包),狀態常量和控制變數

通常情況下 exp-list 為:迭代工廠的呼叫。 即: iter_list() 其返回值是乙個閉包

其執行過程為:

do

-- _f為迭代函式,_s為狀態常量,_var為控制變數

local

_f, _s, _var = explist

while

true

do-- 迭代函式的引數有兩個

-- 第乙個是狀態常量_s, 這個值是explist返回的第二個引數

-- 第二個是控制常量,第一次的值是explist返回的第三個引數,後面的值是上次執行_f返回的第乙個返回值

local var_1, ... , var_n = _f( _s, _var )

-- 接下來_f的第二個引數,變成上一次執行_f返回的第乙個值

_var = var_1

-- 如果控制變數為nil就結束

if_var == nil then

break

endblock

endend

上面的解釋可能一開始看不懂,沒關係,接下來根據例項來說明一下,這裡用最開始那個感謝的函式來說明:

function

list_iter

(t) local i = 0

local n = table.getn(t)

return

function

() i = i + 1

if i <= n then

return t[i] end

endend

helpful_guys =

-- 這裡 in 後面的結果,我們希望是乙個迭代函式,乙個狀態常量,乙個控制常量

-- 但是這裡是 list_iter( helpful_guys )

-- 也就是說 local _f, _s, _var = list_iter( helpful_guys )的返回值

-- 因為list_iter只有乙個返回值,所以這裡的三個變數分別為

-- _f 為閉包, _s = nil, _var = nil

for e in list_iter( helpful_guys ) do

-- 第一次執行_f的時候,返回值是helpful_guys的第乙個元素;"----參與翻譯----"

-- 根據上面分析for的執行過程,可知,這裡就是一直執行_f函式,直到其返回值為nil就就結束

print(e)

end

上面的

for e in list_iter( helpful_guys ) do

print( e )

end

等價於

_f, _s, _var = list_iter( helpful_guys )

for e in _f, _s, _var do

print( e )

end

執行的_f的過程中,其實是有傳入狀態常量_s,和後續變化的控制變數_var,只是這裡閉包函式沒有引數而已

我們可以修改一下迭代工廠,就可以看到狀態常量_s和控制變數_var

function

list_iter

( t )

local i = 0

local n = table.getn( t )

-- _s為狀態常量,其值是迭代工廠返回的第二個值,這裡就是 "我是狀態常量"

-- _var為控制變數,第一次是迭代工廠返回的第三個值,後續是閉包執行返回的第乙個值

return

function

( _s, _var )

print( "狀態常量:", _s )

print( "控制量:", _var )

i = i + 1

if i <= n then

return t[i] end

end, "我是狀態常量", "我是初始的控制變數"

endfor e in list_iter( ) do

print(e)

end

執行結果:

SWfit學習2 函式和閉包

函式 swift 使用 func 關鍵字宣告函式 func greet name string,day string string greet hello day world 通過元組 tuple 返回多個值 func getprices double,double,double getprices...

Swift學習3 函式和閉包

1,函式的返回值可以是元組 2,函式的引數可以有預設值 3,輸入輸出引數 用 可以進行位址傳遞 4,函式型別 可以模擬函式指標,可以作為引數,也可以作為返回值 func stepforward input int int func stepbackward input int int func ch...

Python 閉包和裝飾器學習

def out func func functools.wraps 可以將原函式物件的指定屬性複製個包裝函式物件 functools.wraps func def inner func func,args,kwargs return func return inner func out func d...