1. 程式人生 > >Lua學習筆記--函式初探

Lua學習筆記--函式初探

感覺學習語言的話,函式是個重頭戲。來看一下Lua的函式是神馬樣紙的東東!

一.簡單的函式例子

--一個簡單的函式:階乘
function factorial(num)
	if num == 0 then
		return 1
	else
		return num * factorial(num - 1)
	end
end
恩,這就是個函式。function關鍵字,說明這是個函式,然後是函式名,後面跟的是引數列表,使用括號括起來。函式的結尾需要一個end關鍵字,表明函式結束了。 下面看以下怎麼呼叫:
--一個簡單的函式:階乘
function factorial(num)
	if num == 0 then
		return 1
	else
		return num * factorial(num - 1)
	end
end
--呼叫函式的例子:輸入一個數字,求其階乘
line = io.read()
n = tonumber(line)
if n == nil then
	print("input is not a valid num")
else
	print(factorial(n))
end
結果: 5
120
請按任意鍵繼續. . .
呼叫函式時,有幾個地方需要注意一下: 1.當函式後面只有一個引數,並且這個引數是字串或table構造式時,可以省略括號。 比如:
--函式後面只有一個引數,且為字串
print "hello world"

--函式後面只有一個引數,且為table構造式
print {x = 10, y = 20}
結果: hello world
table: 003BEC40
請按任意鍵繼續. . . 2.呼叫函式時,給出引數如果和要求不符時,不會報錯,處理策略採用:引數多了的捨棄,少了的為nil
function myprint(a, b, c)
	print(a, b, c)
end

--正常呼叫
myprint(1, 2, 3)
--引數多了
myprint(1, 2, 3, 4)
--引數不足
myprint(1, 2)
結果: 1       2       3
1       2       3
1       2       nil
請按任意鍵繼續. . .

二.多重返回值

記得剛學C語言的時候,還不會神馬通過指標引數返回引數的方法,當時就特別糾結,要是有多個返回值得腫麼辦,不過慢慢就習慣了,通過結構體啦,或者指標或者引用實參傳遞多個引數了。沒想到Lua竟然支援多重返回值!!!真的是灰常強大的設定! 一個例子:
--趕腳灰常牛的特性,多個返回值

--一個接受一個table的函式,返回最大元素以及該元素的位置
function maxinum(a)
	local index = 1
	local max = a[index]
	for i, val in ipairs(a) do
	 if val > max then
		max = val
		index = i
	 end
	end
  return max, index
end

--測試
a = {1, 2, 3, 10, 4, 8, 5, 7}
print(maxinum(a))
結果: 10      4
請按任意鍵繼續. . . 當然,多重返回值也不是任何時候都觸發的,Lua會根據不同的情況進行調整。在以下四種情況時,會觸發多重賦值: 1.多重賦值 2.函式呼叫傳入實參列表 3.table構造式 4.return語句 針對不同的情況,看幾個例子

1.多重賦值

--多重返回值demo
function func()
	return 1, 2, 3
end

--正常的多重賦值,按照順序進行多重賦值,返回值個數多了的捨去,少了的取nil
a , b, c = func()
print(a, b, c)

--若函式是多重賦值的最後一個或者唯一一個表示式,那麼會盡可能的保留其返回值
a, b, c = 0, func()
print(a, b, c)

--若函式不是最後一個的話,則只產生一個返回值
a, b, c = func(), 0
print(a, b, c)
結果: 1       2       3
0       1       2
1       0       nil
請按任意鍵繼續. . .

2.函式呼叫傳入實參列表

--多重返回值demo
function func()
	return 1, 2, 3
end

--接受固定引數的myprint()
function myprint(a, b, c)
	print(a, b, c)
end

--當僅有或者為最後一個形參時,會盡可能保留其返回值
print(func())
--myprint僅接受三個引數
myprint(0, func())
--函式表示式為不為最後一個時,僅保留一個返回值
print(func(), 1)
結果: 1       2       3
0       1       2
1       1
請按任意鍵繼續. . . 如果函數出現在一個表示式中,lua會自動將返回值個數調整為1個,即第一個。
--多重返回值demo
function func()
	return 1, 2, 3
end

--當有()括起函式時,即形成了一個表示式,不管函式返回幾個值,僅取一個值
print((func()))
結果:
1
請按任意鍵繼續. . .


3.table構造式

table比較強大,類似vector,想裝多少裝多少,所以,我們在table構造式中返回的值都可以被其吸收。不過,這個行為也是和之前的一樣,僅當只有一個函式作為構造實參時或者函式為最後一個構造實參時才有這種效果,否則又是僅返回一個值。
--多重返回值demo
function func()
	return 1, 2, 3
end

--列印table中所有值的函式
function myprint(a)
	for i, v in ipairs(a) do
		print(v)
	end
	print("--------------------------------")
end

--當僅有一個或者是最後一個構造實參時
a = {func()}
myprint(a)

a = {0, func()}
myprint(a)
--當不是最後一個時,僅能返回一個值
a = {func(), 0}
myprint(a)
結果: 1
2
3
--------------------------------
0
1
2
3
--------------------------------
1
0
--------------------------------
請按任意鍵繼續. . .

4.return語句

return語句本身要返回另一個函式的多個返回值,所以這個時候也支援多個函式的返回值。 例如:
--多重返回值demo
function func()
	return 1, 2, 3
end

--return多個結果

function func2()
	return 1,func()
end

function func3()
	return func(),1
end

--func2呼叫func1,func1在最後會返回1,2,3
print(func2())

--func3呼叫func1,func1不在最後,僅返回1
print(func3())


結果: 1       1       2       3
1       1
請按任意鍵繼續. . .

三.變長引數

這個也是個棒棒噠的特性。使用...表示是變長引數。函式的形參設定為(...)即表明這個函式接受變長引數。一個例子:
--變長引數

--...表示變長引數,使用for迴圈遍歷其中的內容
function add(...)
	local sum = 0
	for i, v in ipairs{...} do
	sum = sum + v
	end
	return sum
end
--使用函式
print(add(1, 2, 3, 4, 5))
結果: 15
請按任意鍵繼續. . . 這裡要注意的是,引數使用這個...表示,這裡面將引數作為一個{...}陣列來遍歷。 關於...其實還是和多返回值的各種特性差不多:
--變長引數

--func
function func(...)
	--直接列印這些引數
	print(...)
	--賦值(多了的捨去,少了的nil)
	a, b = ...
	print("a, b = ", a, b)
	--使用(...)表示只取得第一個
	return (...)
end

print(func(1,2,3))
結果: 1       2       3
a, b =  1       2
1
請按任意鍵繼續. . .  
關於可變引數,可以使用select關鍵字來取得第幾個引數。
--關於可變引數的另一種遍歷方式
function func(...)
	for i = 1, select('#', ...) do
	local arg = select(i, ...)
	print(arg)
	end
end

func(1, 2, 3, 4)
結果: 1
2
3
4
請按任意鍵繼續. . .

四.具名實參

具名實參,給我的趕腳就像一個結構體。我們傳遞一堆引數進來之後,經常忘記這個引數是幹神馬的,以至於最後呼叫的時候弄錯了。所以,這時候,就像C語言那樣,傳遞一個結構體進來,根據結構體的不同欄位,進行操作就不會弄錯了。 Lua中,實現的方法就是使用那個萬能的table。具體的注意事項都在例子中寫出:
--引數使用一個table的構造式,根據其中不同的欄位獲取其值
function Window(option)
	--這裡將引數的各個欄位列印一遍
	print(option.x or 0)--後面的為預設值,如果option.x為nil,則使用預設值
	print(option.y or 0)
	print(option.width or 800)
	print(option.height or 600)
	print("-------------------------------------------")
end

--當引數只有一個table的構造式時,可以省略括號
Window{x = 100, y = 200, width = 1000, height = 800}
--當有引數沒給出時,會使用預設引數
Window{x = 100}
--順序不一樣也是可以的哈
Window{y = 100, width = 1000, x = 100, height = 800}
結果: 100
200
1000
800
-------------------------------------------
100
0
800
600
-------------------------------------------
100
100
1000
800
-------------------------------------------
請按任意鍵繼續. . .

函式入門暫時就這些,還有一個unpack的函式,可以返回table中所有的內容,不過在我的電腦上一直沒能試驗成功,留個坑。