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)
    )
相关文章
相关标签/搜索