Lua 和其他很多語言一樣,函數(shù)調(diào)用時參數(shù)列表被包裹在括號中:
復制代碼 代碼如下:
print('Hello World')
特別的情況是,如果函數(shù)調(diào)用時只有一個參數(shù),并且此參數(shù)為字符串 literal(字面量)或者 table 構(gòu)造器(constructor)時,包裹參數(shù)的括號可以省略:
復制代碼 代碼如下:
print 'Hello World' --> print('Hello World')
type{} --> type({})
Lua 為面向?qū)ο蟮恼{(diào)用提供了特殊的語法:
復制代碼 代碼如下:
o:foo(x) --> o.foo(o, x)
Lua 調(diào)用的函數(shù)可能被定義在 Lua 中,也可能被定義在 C 中(Lua 標準庫中的所有函數(shù)都使用 C 編寫)。
函數(shù)的定義
復制代碼 代碼如下:
function add(a)
local sum = 0
for i = 1, #a do
sum = sum + a[i]
end
return sum
end
print(add{1, 2, 3})
函數(shù)調(diào)用時,實參(arguments)和形參(parameters)個數(shù)可以不匹配,多余的實參會被丟棄,多余的形參值為 nil,例如:
復制代碼 代碼如下:
function f(a, b) print(a, b) end
f(3) --> 3 nil
f(3, 4) --> 3 4
f(3, 4, 5) --> 3 4
函數(shù)多值返回
在 Lua 中函數(shù)可以返回多個值。例如:
復制代碼 代碼如下:
function maximum(a)
local mi = 1
local m = a[mi]
for i = 1, #a do
if a[i] > m then
mi = i; m = a[i]
end
end
return m, mi
end
print(maximum{8, 10, 23, 12, 5})
在多賦值時,多余的值會被丟棄,不足時變量值為 nil:
復制代碼 代碼如下:
x, y = 1 --> x == 1, y == nil
x, y = 1, 2, 3 --> x == 1, y == 2
在函數(shù)調(diào)用時形參的值處理上,在函數(shù)返回值的獲取上,都遵循這個規(guī)則。例如:
復制代碼 代碼如下:
function foo0() end
function foo1() return 'a' end
function foo2() return 'a', 'b' end
x, y = foo2() --> x == 'a', y == 'b'
x = foo2() --> x == 'a'
x, y, z = 10, foo2() --> x == 10, y == 'a', z == 'b'
t = { foo2() } --> {'a', 'b'}
再看一個例子:
復制代碼 代碼如下:
function foo2() return 'a', 'b' end
x, y = foo2(), 20 --> x == 'a', y == 20
這里,由于函數(shù)調(diào)用不是在列表的最后一個位置,這時候函數(shù)只提供一個值。一個更有意義的例子:
復制代碼 代碼如下:
function foo2() return 'a', 'b' end
print(foo2()) --> a b
print(foo2(), 1) --> a 1
如果函數(shù)調(diào)用在列表的最后一個位置,同時使用 () 包裹函數(shù)調(diào)用,這時候函數(shù)也只提供一個值:
復制代碼 代碼如下:
function foo2() return 'a', 'b' end
print(foo2()) --> a b
print((foo2())) --> a
一個比較有用的利用函數(shù)多值返回的特性的函數(shù)是 table.unpack,它接受一個數(shù)組作為參數(shù),返回數(shù)組中的所有元素:
復制代碼 代碼如下:
print({10, 20, 30}) --> table: 00000000005BBE00
print(table.unpack{10, 20, 30}) --> 10 20 30
變長參數(shù)
我們在使用 print 函數(shù)的時候可以傳遞任意數(shù)目的參數(shù)。Lua 提供了 … 表示參數(shù)列表,讓我們實現(xiàn)類似 print 的函數(shù):
復制代碼 代碼如下:
function add(...)
local s = 0
for _, v in ipairs{...} do
s = s + v
end
return s
end
print(add(3, 4, 5)) --> 12
再一個例子:
復制代碼 代碼如下:
function test(...)
local a, b = ...
print(a, b)
end
test(1, 2, 3) --> 1 2
還有一個特殊情況,我們需要注意:
復制代碼 代碼如下:
function p(...)
for _, v in ipairs{...} do
print(v)
end
end
p(1, nil, 3) --> 1
print(1, nil, 3) --> 1 nil 3
上例可以看到,我們的 p 函數(shù)在參數(shù)中存在 nil 時并非按我們的意愿輸出了結(jié)果。Lua 提供了一個 table.pack 函數(shù),用于獲取其調(diào)用參數(shù)(包括 nil 參數(shù))并返回一個包含所有參數(shù)的 table,此 table 存在一個額外的域 n,用于表示參數(shù)的數(shù)量:
復制代碼 代碼如下:
function p(...)
local arg = table.pack(...)
for i = 1, arg.n do
print(arg[i])
end
end
p(1, nil, 3, nil) --> 1 nil 3 nil
不過需要注意的是,{…} 相比 table.pack(…) 來說更加高效,我們可以在確保沒有 nil 參數(shù)的時候使用。
函數(shù)是第一類值(first-class values)
我們能夠像使用其他變量一樣的使用函數(shù):
復制代碼 代碼如下:
a = { p = print }
a.p('Hello World') --> Hello World
print = math.sin
a.p(print(1)) --> 0.8414709848079
類似于 {} 作為 table 的構(gòu)造器,我們可以認為 function(x) end 為函數(shù)的構(gòu)造器:
復制代碼 代碼如下:
local add = function(a, b)
return a + b
end
print(add(1, 2))
-- 另一種寫法
local function add(a, b)
return a + b
end
table.sort 函數(shù)用于排序,它可以接受一個排序函數(shù)作為參數(shù):
復制代碼 代碼如下:
network = {
{ name = "grauna", IP = "210.26.30.34" },
{ name = "arraial", IP = "210.26.30.23" },
{ name = "lua", IP = "210.26.23.12" },
{ name = "derain", IP = "210.26.23.20" },
}
print('--------------')
for _, v in ipairs(network) do
print(v.name)
end
table.sort(network, function(a, b)
return a.name > b.name
end)
print('--------------')
for _, v in ipairs(network) do
print(v.name)
end
輸出結(jié)果為:
復制代碼 代碼如下:
--------------
grauna
arraial
lua
derain
--------------
lua
grauna
derain
arraial
在此例中,我們提供的排序函數(shù)作為一個參數(shù)傳遞給 table.sort 函數(shù),像此排序函數(shù)這樣沒有名字的函數(shù)被叫做匿名函數(shù)。
閉包(closures)
很多語言都支持閉包(Golang、JavaScript 等)。一個函數(shù)和其訪問的外部變量組成一個閉包??匆粋€例子:
復制代碼 代碼如下:
function newCounter()
local i = 0
return function()
i = i + 1
return i
end
end
c1 = newCounter()
print(c1()) --> 1
print(c1()) --> 2
這里的 c1 就是一個閉包(外部變量為 i),每次調(diào)用 newCounter 都會創(chuàng)建一個閉包(并創(chuàng)建一個新的變量 i):
復制代碼 代碼如下:
c2 = newCounter()
print(c2()) --> 1
print(c1()) --> 3
print(c2()) --> 2
您可能感興趣的文章:- Lua腳本語言簡明入門教程
- Lua極簡入門指南(一):基礎(chǔ)知識篇
- Lua極簡入門指南(三): loadfile和錯誤處理
- Lua極簡入門指南:全局變量
- lua腳本語言快速入門教程
- Lua入門學習筆記
- Lua極簡入門指南(六):模塊
- Lua 極簡入門指南(七):面向?qū)ο缶幊?/li>
- Lua腳本語言基本語法快速入門教程
- Lua語言新手簡單入門教程