Lua探路(2):函數

函數基礎

(1)函數

格式:

function fun_name(params)
--body
end

調用方式:

o.fun(x) 或  o:fun(x)

其中冒號調用方式會隱含將o作爲函數第一個參數傳入;

參數:形參和實參數量可以不同,規則和多重賦值一致;

多重返回值:只需在return時這樣寫

return a, b, c

print可以接受不同數量的實參,多重返回值的函數可以直接作爲其它函數的參數,也可以作爲table的構造式 –> a = {f()};

(2)table.unpack

返回數組中所有值

print(table.unpack({10, 20, 30}))
local a = {10, 20, 30}
print(table.unpack(a))
local a = {}
a[1] = 10;
a[2] = 20;
a[3] = 30;
print(table.unpack(a))
(3)變長參數

lua的函數可以接受不同數量的實參

function add(...)
 -- body
 local s = 0
 for i,v in ipairs{...} do  --注意這裏是大括號
  s = s + v
 end
 return s
end

print(add(3,4, 10, 25, 12))    --54

參數表中三個點(…)表示該函數可接受不同數量的實參。
表達式(…)的行爲類似一個具有多重返回值的函數。
把第一個和第二個參數賦給a和b :local a, b = …
可以像訪問數組一樣去訪問可變參數。
select(p1, p2):p1爲數字n,那麼select返回它第n個可變實參;p1爲‘#’select返回變長參數的總數。

function fun( ... )
 -- body
 local len = select('#', ...) -- 獲取長度
 local params = {...}
 for i=1,len do
  print(params[i])
 end
end

fun(3, 4, 10, 25, 12)
(4)具名實參

傳遞table


函數進階

(1)匿名函數

在lua中,函數是一種第一類值,就是和其它傳統類型一樣可以存儲到變量或table中,可以作爲實參傳遞給其它函數,還可以作爲其它函數的返回值。
函數與所有其它值一樣都是“匿名”的:函數定義有一下兩種方法,表明fun只是一個持有函數的變量,而不是函數的名稱。

unction fun( ... )
 -- body
end

fun = function( ... )
 -- body
 print('fun')
end

使用匿名函數:

local tb = {
 {name = "grauna", level = "50"},
 {name = "lua", level = "10"},
 {name = "arraial", level = "30"}
}

table.sort( tb,
 function(a, b)  --匿名函數
  return (a.name < b.name)
 end)

print(tb[1].name)
print(tb[2].name)
print(tb[3].name)

table.sort用於對table中元素排序

(2)閉合函數

在函數內部定義的函數,能夠通過建立一個閉合函數(closure),在外部函數已經執行完畢的情況下,還能訪問到在外部函數中的局部變量。

後來發現一個規律:所有定義在函數內部的函數,都不能直接在外部函數外部訪問,只能通過外部函數把內部函數返回出來,這樣在外部函數的外部纔可以使用,這也就是閉包函數通俗的理解吧。例如下面代碼中的 c1、c2

function fun()
 -- body
 local i = 1
 print(i);
 return function()   --返回了閉包函數
  -- body
  i = i+1
  return i
 end
end

c1 = fun() --創建閉合函數 c1
c2 = fun() --創建閉合函數 c2                  注意:這裏進行的操作其實是執行了fun函數,但並沒有執行匿名函數,而是把匿名函數賦值給c1、c2了,所以c1()、c2()其實執行裏面匿名函數

print(c1()) --也可以print(fun()())這樣調用,print(fun())打印是fun函數裏面的匿名函數的地址
print(c1())
print(c1())

--輸出 1 2 3 4

在fun函數中匿名函數,仍能訪問到fun作用域下的局部變量,i 對於匿名函數來講被稱作“非局部變量”。其中c1和c2是同一個函數創建的兩個不同的closure,它們各自擁有局部變量的獨立實例。

(3)非全局函數

函數可以存儲在全局變量、局部變量、table字段中。只要將函數存到一個局部變量中,該函數只能在某個特定的作用域使用。
定義:

local a = function()
 -- body
end
local function a()
 -- body
end
(4)尾調用消除

尾調用:當 f 調用完 g 之後就再無其他事情可做了,這種情況下,當 g 返回時,執行控制權直接返回到調用 f 的那個點上。
消除:在尾調用之後,程序不需要保存任何關於該函數的棧信息了,使得在進行尾調用時不耗費任何棧空間。

function f()
 -- body
 print("f")

 g()  -- g()是函數f的最後調用
end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章