lua學習之函數篇

函數

  1. 函數是對語句和表達式進行抽象的主要機制

兩種用法數組

  1. 一是能夠完成特定的任務,一句函數調用被視爲一條語句
  2. 二是以只用來計算並返回特定的結果,視爲一句表達式
print("Hello, World")
a = math.sin(3) + math.cos(10)
print(os.date())
  1. 不管哪一種用法都須要將全部參數放到一對圓括號中
  2. 但若是參數是字面字符串或 table 構造式的話,能夠放在括號中,也能夠不放
  3. 即便在調用函數時沒有參數,也必須有一個 () 空括號,如調用 os.date()
print "Hello, World" -- 等價於 print("Hello, World")
print {1, 2, 3} -- 等價於 print({1, 2, 3})

function add(a)
    local sum = 0
    for i, v in ipairs(a) do
       sum = sum + v 
    end
    return sum
end
b = {1, 2, 3}
add(b)
  1. function 是定義函數的關鍵字
  2. add 是函數名
  3. a 是函數的形式參數,是函數定義式參數列表中的參數
  4. add(b) 調用這個函數所傳入的參數稱爲實際參數
  5. 調用函數的實際參數的個數能夠與函數定義時的形式參數個數不一樣
  6. lua 會自動調整實參的數量,以匹配參數表的要求,這和多s重賦值相似
  7. 若實參少於形參,多餘的形參被初始化爲 nil
  8. 若實參多餘形參,多餘的實參被拋棄
  9. lua 程序既可使用 以 lua 編寫的函數,也可以使用 C 語言編寫的函數
function f(a, b)
    return a or b
end
f(3) -- a = 3, b = nil
f(3, 4) -- a = 3, b = 4
f(3, 4, 5)  -- a = 3, b = 4 ,5 被丟棄了

定義一個全局的計數器函數

function intCount(n)
    n = n or 1  -- 賦值一個默認值
    count = count + 1
end

面向對象式調用函數lua

  1. o.foo(o, x)
  2. o:foo(x) 等價於 o.foo(o, x)
  3. 冒號操做符使得咱們在調用 o.foo 時隱含地將 o 做爲函數的第一個參數

多重返回值

  1. lua 容許函數返回多個結果
  2. 如標準庫中的一些預約義函數
-- 用於在字符串中定位一個模式的函數 string.find
print(string.find("Hello Lua users", "Lua")) -- 開始的位置 7, 結束的位置 9
  1. 在 return 後列出須要返回的全部值便可,用 , 逗號分隔
-- 查找數組中的最大元素,並返回這個元素的所在位置
function maximum(a)
    local mi = 1 -- 最大值的索引
    local max = a[mi] -- 最大值
    for i,v  in ipairs(a) do
        if v > max then
            mi = i
            max = v
        end
    end
    return max, mi
end
maximum(a) -- 沒有任何反應
print(maximum({3, 4, 23, 5, 7})  -- 23 3
print(maximum({3, 4, 23, 5, 7} .. "a") -- 23a
  1. 若是將函數調用做爲單獨的語句執行,lua 會丟棄全部的返回值
  2. 若是將將函數做爲表達式的一部分調用,只保留函數的第一個返回值
  3. 只有當函數是一系列表達式中的最後一個元素(或只有一個元素的時候),纔會獲取全部的返回值

一系列表達式在 Lua 中的 4 中狀況調試

  1. 多重賦值
  2. 函數調用時傳入的實參列表
  3. table 構造式
  4. return 語句

多重賦值code

  1. 在多重賦值中,若是一個函數調用是最後(或僅有)的一個表達式,lua 會保留儘量多的返回值,用來匹配賦值的變量
  2. 若是一個函數沒有返回值或沒有返回足夠多的返回值,那麼 lua 會用 nil 來補充缺失的值
  3. 若是一個函數調用不是一系列表達式中的最後一個元素,就只能返回一個值
  4. 若是一個函數調用做爲另外一個函數調用的最後一個(或僅有的)實參的時候,第一個函數的全部返回值都會做爲實參傳遞給另外一個函數
function foo0() end
function foo1() return "a" end
function foo2() return "a", "b" end
-- 多重賦值的4種狀況
-- 第一種狀況
x, y = foo2() -- x = "a" , y = "b"
x = foo2() -- x = "a"
x, y, z = 10, foo2() -- x = 10, y = "a", z = "b"
-- 第二種狀況
x, y = foo0() -- x = nil, y = nil
x, y = foo1() -- x = "a", y = nil
x, y, z = foo2() -- x = "a", y = "b", z = nil
-- 第三種狀況
x, y = foo2(), 20 -- x = "a", y = 20
x, y = foo0(), 20, 30 -- x = nil, y = 20
-- 第四種狀況
print(foo0()) -- 不會打印任何值
print(foo1()) -- a
print(foo2()) -- a, b
print(foo2(), 20) -- a, 1
print(foo2() .. "x") -- ax

table 構造式orm

  1. table 構造式能夠完整地接收一個函數調用的全部結果,即不會有任何數量方面的調整
  2. 但這種行爲,只有當一個函數調用做爲最後一個元素時纔會發生
  3. 其餘位置上的函數調用老是隻產生一個結果值
function foo0() end
function foo1() return "a" end
function foo2() return "a", "b" end
t = {foo2()} -- t = {"a", "b"}
t = {foo2(), "x"} -- t = {"a", "x"}

return對象

  1. 將函數調用放入一對圓括號 () 中,使其只返回一個結果
  2. return 語句後面的內容不須要 () 圓括號
  3. 若是強行加上則會使一個多返回值的函數,強制其只返回一個 return(f())
function foo0() end
function foo1() return "a" end
function foo2() return "a", "b" end
function foo(i)
    if i == 0 then return foo0() 
        elseif i == 1 then return foo1() 
        elseif i == 2 then return foo2() 
    end
end
print(foo(1)) -- a
print(foo(2)) -- a, b
print(foo(0)) -- 無返回值

-- () 包裹
print((foo(1)) -- a
print((foo(2)) -- a
print((foo(0)) -- nil 不太懂爲何

unpack 函數遞歸

  1. 接收一個數組做爲參數
  2. 並從下標 1 開始返回該數組的全部元素
  3. 這個預約義函數由 C 語言編寫
print(unpack{10, 20, 30}) -- 10 20 30
a, b = unpack{10, 20, 30}  -- a = 10, b = 20
  1. 用於泛型調用
  2. 泛型調用就是能夠以任何實參來調用任何函數
-- 調用任意函數 f, 而全部的參數都在數組 a 中
-- unpack 將返回 a 中的全部值,這些值做爲 f 的實參
f(unpack(a)) 
f = string.find
a = {"hello", "ll"}
f(unpack(a)) -- 3 4 等效於 string.find("hello", "ll")

用 lua 遞歸實現 unpack索引

function unpack(t, i)
    i = i or 1
    if t[i] then
        return t[i], unpack(t, i + 1)
    end
end

變長參數

  1. lua 中的函數能夠接收不一樣數量的實參
  2. 當這個函數被調用時,它的全部參數都會被收集到一塊兒
  3. 這部分收集起來的實參稱爲這個函數的「變長參數」
  4. ... 3個點表示該函數接收不一樣數量的實參
  5. 一個函數要訪問它的變長參數時,須要用 ... 三個點,此時 ... 三個點是做爲一個表達式使用的
  6. 表達式 ... 三個點的行爲相似一個具備多重返回值的函數,它返回的是當前函數的全部變長參數
  7. 具備變長參數的函數也能夠擁有任意數量的固定參數
  8. 但固定參數必定要在變長參數以前
  9. 當變長參數中包含 nil ,則須要用 select 訪問變長參數
  10. 調用 select 時,必須傳入一個固定參數 selector(選擇開關) 和一系列變長參數
  11. 若是 selector 爲數字 n ,那麼 select 返回它的第 n 個可變實參
  12. 不然,select 只能爲字符串 "#" ,這樣 select 會返回變長參數的總數,包括 nil
-- 返回全部參數的和
function add(...)
    local s = 0
    for i, v in ipairs{...} do -- 表達式{...}表示一個由變長參數構成的數組
        s = s + v
    end
    return s
end
print(add(3, 4, 5, 100)) -- 115

-- 調試技巧 ,相似與直接調用函數 foo ,但在調用 foo 前先調用 print 打印其全部的實參
function foo1(...)
    print("calling foo:", ...)
    return foo(...)
end


-- 獲取函數的實參列表
function foo(a, b, c) end
function foo(...)
        local a, b, c = ...
end
-- 格式化文本 string.format ,輸出文本 io.write
-- 固定參數必定要在變長參數以前
function fwrite(fmt, ...)
    return io.write(string.format(fmt, ...))
end
fwrite() -- fmt = nil
fwrite("a") -- fmt = a 
fwrite("%d%d", 4, 5) -- fmt = "%d%d" , 變長參數  = 4, 5

for i = 1, select('#', ...) do
    local arg = select('#', ...)
    <循環體>
end

具名參數

  1. lua 中的參數傳遞機制是具備 「位置性」的
  2. 就是說在調用一個函數時,實參是經過它在參數表中的位置與形參匹配起來的
  3. 第一個實參的值與第一個形參相匹配,依此類推
  4. 定義:經過名稱來指定實參
  5. 可將全部的實參組織到一個 table 中,並將這個 table 做爲惟一的實參傳給函數
  6. lua 中特殊的函數調用語法,當實參只有一個 table 構造式時,函數調用中的圓括號是無關緊要的
os.rename  -- 文件更名,但願達到的效果 os.rename(old = "temp.lua", new = "temp1.lua")
-- lua 不支持註釋的寫法
rename = {old = "temp.lua", new = "temp1.lua"}
function rename (arg)
    return os.rename(arg.old, arg.new)
end

x = Window{x = 0, y = 0, width = 300, height = 200, title = "Lua", background = "blue", border = "true"}

-- Window 函數根據要求檢查必填參數,或爲某些函數添加默認值
-- 假設 _Window 是真正用於建立新窗口的函數,要求全部參數以正確次序傳入
function Window(options)
    if type(options.title) ~= "string" then
        error("no title")
    elseif type(options.width) ~= "number" then
        error("no width")
    elseif type(options.height) ~= "height" then
        error("no height")
    end
    _Window(options.title,
        options.x or 0 -- 默認值
        options.y or 0 -- 默認值
        options.width, options.height,
        options.background or "white" -- 默認值
        options.border -- 默認值爲 false(nil)
    )
相關文章
相關標籤/搜索