Lua程序設計 closure(閉合函數)

        若將一個函數寫在另外一個函數以內,那麼這個位於內部的函數即可以訪問外部函數中的局部變量,這項特徵稱之爲「詞法域」。函數

        假設有一個學生姓名的列表和一個對應於每一個姓名的年級列表,須要根據每一個學生的年紀來對他們的姓名進行排序。lua

names = {"Peter", "Paul", "Mary"}
grades = {Mary = 10, Paul = 7, Peter = 8}
table.sort(names, function(n1, n2)
      return grades[n1, n2] --比較年級
     end) 
     
如今,假設要單首創建一個函數來作這項工做:
function sortbygrade(names,grades)
 table.sort(names, function(n1, n2)
     return grades[n1] > grade[n2]  --比較年級
    end)
end
注意:上例中傳遞給sort的匿名函數能夠訪問參數grades,而grades是外部函數sortbygrade的局部變量。在這個匿名函數的內部,grades既不是全局變量也不是局部變量,將其稱爲一個「非局部的變量」。
由於函數是「第一類值」的緣由,因此容許這樣訪問。

 

function newCounter()
local i = 0
return function ()  --匿名函數
    i = i + 1
    return i
    end
end 

c1 = newCounter()
print(c1())  -->1
print(c1())  -->2
   這段代碼中,匿名函數訪問了一個「非局部的變量」i,該變量用於保持一個計數器。初看上去,因爲建立變量i的函數已經返回,因此以後每次調用匿名函數時,i都應是已超出了做用範圍的,可是,Lua會以closure的概念來處理。
   簡單的講,一個closure就是一個函數加上該函數所需訪問的全部「非局部變量」。若是再次調用newCounter,那麼它會建立一個新的局部變量i,從而也將獲得一個新的closure。
   
  c2 = newCounter()
  print(c2())  --- >1
  print(c1())  --- >3
  print(c2()) --- >2
  所以,c1和c2是同一個函數所建立的兩個不一樣的closure,它們各自擁有局部變量i的獨立實例。

         從技術上講,Lua中只有closure而不存在「函數」,由於函數自己就是一種特殊的closure【closure:指一個函數以及一系列這個函數會訪問到「非局部的變量」,所以若一個closure沒有那些會訪問的「非局部變量」,那他就是一個傳統概念中的「函數」】。spa

       Lua中函數是存儲在普通變量中的,所以能夠輕易地從新定義某些函數,甚至是從新定義那些預約義的函數。一般當從新定義一個函數的時候,須要在新的實現中調用原來的那個函數。code

 oldSin = math.sin
math.sin = function(x) return oldSin(x * math.pi/180) end
假設要從新定義函數sin,使其參數能使用角度來代替原先的弧度。這個新函數就必須得轉換它的實參,並調用原來的sin函數完成真正的計算。
相關文章
相關標籤/搜索