Lua学习之function
来源:互联网 发布:淘宝充值店没有人买 编辑:程序博客网 时间:2024/04/30 02:52
第五章 Lua学习笔记之函数
函数有两个用途
1. 完成指定功能,函数作为调用语句使用
2. 计算并返回值,函数作为赋值语句的表达式使用
function unpack(t,i)
i = i or 1
if t[i] then
return t[i],unpack(t,i + 1)
end
end
Lua 中的函数和 Javascript 中的有些相似,函数在书写的时候,前面都需要加上 function 这个关键字, 上篇文章中提过 function 这个关键字,他在 Lua 中也是一种类型。下面我们来看看 Lua 中的一个简单函数是怎么写的。
- function printHello(a,b) --a,b为参数
- print(a,b);
- print("Hello")
- end
在上面的一段函数中,函数的开头需要function 关键字来修饰它,表明它是一个“函数类型” ,当然既然成为“类型” 我们在程序中也可以这样写:
- testFuction=function (a,b) return a+b end
- --testFuction就相当于这个函数的函数名了
所以说,Lua 的函数是很灵活的。
在C/C++中我们总是用"{ }" 来括起一个函数,但是Lua中有所不同,大家也注意到了上边的代码,最后跟随着一个 "end" ,这个 end 就是来表明一个函数的结尾的。好了对于Lua中函数的初步认识就到这里,更深入的我们要留在以后实践中来体会。
lua函数接受可变参数,lua讲函数的参数放在一个叫arg的表中,除了参数之外,表中还有一个域n表示参数个数
function g(a,b,…)end
g(3) a = 3,b = nil,arg = {n = 0}
g(3,4) a = 3,b = 4, arg = {n=0}
g(3,4,5,6) a = 3,b = 4,arg = {5,6,n = 2}
如果只想要string.find返回的第二个值:
一个典型的方法是使用虚变量(下划线)
s = "12345678"
p = "3456"
local _, x = string.find(s,p)
print(x)
命名参数
Lua的函数参数和位置相互关联,调用时实参安顺序依次传给形参。
有时候用名字指定参数是很有用的。
比如用rename函数给一个文件重新命名,有时候我们记不得命名前后两个参数的顺序了
Function rename(arg)
Return os.rename(arg.old,arg.new)
end
Rename{old = “temp.lua”,new=”temp1.lua”}
当函数参数很多时,这样处理就比较方便,简单。例如窗口创建函数;
w = Window {
x = 0,y = 0,width = 300,height = 200,
title = "lua",background = "blue",
border = true
}
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) ~= "number" 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
)
End
第六章再论函数
Lua中的函数有以下两个特点:
1. lua中的函数和其他变量(string,number) 一样,可以赋值,可以放在变量中,可以放在表中。可以作为函数参数,可以作为函数返回值。
2. 被嵌套的内部函数可以访问他外面的数据成员
3. Lua函数可以是匿名的,当我们提到函数名(比如print),其实是print这个变量指向打印输出这个函数,当然,打印输出函数也可以由其他变量指向。例如:
a = { p = print}
a.p("hello world")
print = math.sin
a.p(print(1))
sin = a.p
sin(10,20)
没错,函数就是变量,就是值。
function foo(x)
return 2*x
end
foo = function (x)
return 2*x end
函数定义就是把function这个值赋值给foo这个变量。
我们使用function(x)…end 创建函数和 {}创建表是一个道理。
Table标准库有一个排序函数,接受一个表作为参数对标中的元素进行排序。
这个函数必须对不同类型的元素进行升降排序,Lua不是尽可能多的传入参数解决这种问题,而是接受一个排序函数作为参数,(类似c++的函数指针)排序函数作为输入参数,并且返回两个参数比较后的大小关系(用c++可以实现这个万能的排序算法)
例如:
name = { "peter","paul","mary"}
grades = { mary = 10,paul = 7,peter = 13 }
table.sort(name, function (n1,n2) return grades[n1] > grades[n2] end )
在lua中,其他函数作为函数的参数,成这个函数为高级函数,没有什么特殊的地方。
function sortbygrade (name,grades)
table.sort(name,function (n1,n2) return grades[n1] > grades[n2] end)
end
闭包
包含在sortbygrade中的sort的参数匿名function 可以访问sortbygrade的grades在匿名function 内部grades既不是全局变量,也不是局部变量。他别称为外部的局部变量或upvalue
function newCounter()
local i = 0
return function ()
i = i + 1
return i
end
end
ca = newCounter()
cb = newCounter()
print(ca())
print(ca())
print(cb())
匿名函数使用upvalue i保存他的计数
当我们调用匿名函数的时候I已经超出了他的适用范围,因为创建i的函数newCounter已经返回了。简单滴说闭包是一个函数加上他可以正确访问的upvalues,如果我们再次调用newCOunter,将创建一个新的局部变量i
因此我们得到了一个作用在新建的i上的新闭包。
技术上讲,闭包是值而不是函数。函数仅仅是闭包的一个原形声明;我们继续使用术语函数代替闭包。
闭包的功能:
作为高级函数的参数。
作为函数嵌套的函数。
作为回调函数。
创建沙箱。
do
local oldOpen = io.open
io.open = function (filename,mode)
if access_OK(filename,mode) then
return oldOpen(filename.mode)
else
return nil,"access denied"
end
end
end
非全局函数
Lua中函数分为全局和非全局
大部分作为table的域(math.sin io.read)
例如:
--1.表和函数在一起
Lib = {}
Lib.foo = function (x,y) return x + y end
Lib.goo = function (x,y) return x - y end
--2.使用表构造函数
Lib = {
foo = function (x,y) return x + y end,
goo = function (x,y) return x - y end
}
--3.Lua提供另一种语法方式
Lib = {}
function Lib.foo (x,y)
return x + y
end
function Lib.go0 (x,y)
return x - y
end
当我们把函数赋值给局部变量时,函数成了局部的,就是说局部函数像局部变量一样在一定范围内有效。声明局部函数的方式:
Local f = function(…)
…
End
Local function f (…)
….
end
需要注意声明递归局部函数
Local face—声明和定义必须分开
face = function(n)
If(n==1)
Return 1
Else
Return n*face(n-1)
End
End
尾调用:
如果函数最后一句执行的是函数调用,我们称这种调用为尾调用
Function f(x)
Return g(x)
End
--g(x)即为尾调用
例子中f调用g之后不会做任何事情
这时候,g不需要返回到f,所以尾调用之后,栈不保存f的任何信息。
由于尾调用不需要栈空间,所以尾调用递归可以无限次进行
Function foo(n)
If(n>0)then
Return foo(n-1)
End
End
需要注意:为调用之后确实不做什么事,不做什么事的调用不一定是尾巴调用
例如:
Function f(x)
G(x)
R
return
end
--不是尾调用
下面的例子也不是尾调用
Return g(x)+1
Return(g(x))
Return x or g(x)
以上表达式的最后一步计算的不是g(x)本身,所以不是尾函数
- local function languageTest()
- -- table test
- local names = {"Peter", "Paul", "Mary"}
- local grades = {Mary=10, Paul=7, Peter=8}
- table.sort(names, function(n1, n2)
- return grades[n1] > grades[n2]
- end)
- for i=1, #names do
- print(names[i])
- end
- -- function test
- local function newCounter(name)
- local i = 0
- return function()
- i = i+1
- return name .. ":" .. i
- end
- end
- local c1 = newCounter("c1")
- local c2 = newCounter("c2")
- print(c1())
- print(c1())
- print(c2())
- print(c1())
- print(c2())
- -- for test
- local function values(t)
- local i = 0;
- return function() i=i+1; return t[i] end
- end
- for elm in values(names) do
- print(elm)
- end
- -- -- for test2
- -- for k in pairs(names) do
- -- print(k)
- -- end
- end
- local function tableTest()
- local Set = {}
- local mt = {}
- -- create a new set with teh values of the given list
- Set.new = function(l)
- local set = {}
- setmetatable(set, mt)
- for _, v in ipairs(l) do set[v] = true end
- return set;
- end
- Set.union = function(a, b)
- if getmetatable(a) ~= mt or getmetatable(b) ~= mt then
- error("attempt to 'add' a set with a non-set value", 2);
- end
- local res = Set.new {}
- for k in pairs(a) do res[k] = true end
- for k in pairs(b) do res[k] = true end
- return res
- end
- Set.intersection = function(a, b)
- local res = Set.new {}
- for k in pairs(a) do
- res[k] = b[k]
- end
- return res
- end
- Set.tostring = function(set)
- local l = {}
- for e in pairs(set) do
- l[#l+1] = e
- end
- return "{" .. table.concat(l, ", ") .. "}"
- end
- Set.print = function(s)
- print(Set.tostring(s))
- end
- mt.__add = Set.union
- mt.__mul = Set.intersection
- mt.__tostring = Set.tostring
- mt.__le = function(a, b)
- for k in pairs(a) do
- if not b[k] then return false end
- end
- return true
- end
- mt.__lt = function(a, b)
- return a<=b and not (b<=a)
- end
- mt.__eq = function(a, b)
- return a<=b and b<=a
- end
- local s1 = Set.new {10, 20, 30, 50}
- local s2 = Set.new {30, 1}
- local s3 = s1+s2+s2
- -- local s3 = s1+s2+s2 + 8
- Set.print(s3)
- Set.print((s1+s2)*s1)
- s1 = Set.new{2, 4}
- s2 = Set.new{4, 10, 2}
- print(s1<=s2)
- print(s1<s2)
- print(s1>=s2)
- print(s1>s2)
- print(s1==s2*s1)
- s1 = Set.new {10, 4, 5}
- print(s1)
- -- mt.__metatable = "not your business"
- -- print(getmetatable(s1))
- -- setmetatable(s1, {})
- local Window = {} -- create a namespace
- --create teh prototype with default values.
- Window.prototype = {x=0, y=0, width=100, height=100}
- Window.mt = {} -- create a metatable
- --declare the constructor function
- function Window.new(o)
- setmetatable(o, Window.mt)
- return o
- end
- Window.mt.__index = function(table, key)
- return Window.prototype[key]
- end
- -- Window.mt.__index = Window.prototype
- w = Window.new {x=10, y=20}
- print(w.x)
- -- Tables with default values
- local function setDefault(t, d)
- local mt = {__index = function() return d end}
- setmetatable(t, mt)
- end
- local tab = {x=10, y=20}
- print(tab.x, tab.z)
- setDefault(tab, 0)
- print(tab.x, tab.z)
- local mt = {__index = function(t) return t.___ end }
- local function setDefault(t, d)
- t.___ = d
- setmetatable(t, mt)
- end
- -- Tracking table accesses
- local t = {} -- original table (created somewhere)
- -- keep a private access to the original table
- local _t = t
- -- create proxy
- t = {}
- -- create metatable
- local mt = {
- __index = function(t, k)
- print("*access to element " .. tostring(k))
- return _t[k]
- end,
- __newindex = function(t, k, v)
- print("*update of element " .. tostring(k) .. " to " .. tostring(v))
- _t[k] = v -- update original table
- end
- }
- setmetatable(t, mt)
- t[2] = "hello"
- print(t[2])
- -- Read-only tables
- function readOnly(t)
- local proxy = {}
- local mt = {
- __index = t,
- __newindex = function(t, k, v)
- error("attempt to update a read-only table", 2)
- end
- }
- setmetatable(proxy, mt)
- return proxy
- end
- days = readOnly {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
- print(days[1])
- -- days[2] = "Noday"
- end
- local function objectTest()
- local Account = {
- balance = 0,
- new = function(self, o)
- o = o or {} -- create table is user does not provide one
- setmetatable(o, self)
- self.__index = self
- return o
- end,
- withdraw = function(self, v)
- if v>self.balance then error"insufficient funds" end
- self.balance = self.balance - v
- end,
- deposit = function(self, v)
- self.balance = self.balance + v
- end
- }
- local a = Account:new {balance = 0}
- a:deposit(100.00)
- print(a.balance)
- local b = Account:new()
- print(b.balance)
- b.balance = 123
- print(b.balance)
- b:withdraw(100)
- print(b.balance)
- print(a.balance)
- -- inheritance
- local SpecialAccount = Account:new({
- withdraw = function(self, v)
- if v - self.balance >= self:getLimit() then
- error"insufficient funds"
- end
- self.balance = self.balance - v
- end,
- getLimit = function(self)
- return self.limit or 0
- end
- })
- local s = SpecialAccount:new {limit=1000.00}
- s:deposit(100.00)
- s:withdraw(200.00)
- print("s:", s.balance)
- end
- local function main()
- languageTest();
- tableTest();
- objectTest();
- end
- main()
local function languageTest() -- table testlocal names = {"Peter", "Paul", "Mary"}local grades = {Mary=10, Paul=7, Peter=8}table.sort(names, function(n1, n2) return grades[n1] > grades[n2]end)for i=1, #names doprint(names[i])end-- function testlocal function newCounter(name)local i = 0return function()i = i+1return name .. ":" .. iendendlocal c1 = newCounter("c1")local c2 = newCounter("c2")print(c1())print(c1())print(c2())print(c1())print(c2())-- for testlocal function values(t)local i = 0;return function() i=i+1; return t[i] endendfor elm in values(names) doprint(elm)end---- for test2--for k in pairs(names) do--print(k)--endendlocal function tableTest() local Set = {}local mt = {}-- create a new set with teh values of the given listSet.new = function(l)local set = {}setmetatable(set, mt)for _, v in ipairs(l) do set[v] = true endreturn set;endSet.union = function(a, b)if getmetatable(a) ~= mt or getmetatable(b) ~= mt thenerror("attempt to 'add' a set with a non-set value", 2);endlocal res = Set.new {}for k in pairs(a) do res[k] = true endfor k in pairs(b) do res[k] = true endreturn resendSet.intersection = function(a, b)local res = Set.new {}for k in pairs(a) do res[k] = b[k]endreturn resendSet.tostring = function(set)local l = {}for e in pairs(set) do l[#l+1] = eendreturn "{" .. table.concat(l, ", ") .. "}"endSet.print = function(s)print(Set.tostring(s))endmt.__add = Set.unionmt.__mul = Set.intersectionmt.__tostring = Set.tostringmt.__le = function(a, b)for k in pairs(a) do if not b[k] then return false endendreturn trueendmt.__lt = function(a, b)return a<=b and not (b<=a)endmt.__eq = function(a, b)return a<=b and b<=aendlocal s1 = Set.new {10, 20, 30, 50}local s2 = Set.new {30, 1}local s3 = s1+s2+s2--local s3 = s1+s2+s2 + 8Set.print(s3)Set.print((s1+s2)*s1)s1 = Set.new{2, 4}s2 = Set.new{4, 10, 2}print(s1<=s2)print(s1<s2)print(s1>=s2)print(s1>s2)print(s1==s2*s1)s1 = Set.new {10, 4, 5}print(s1)--mt.__metatable = "not your business"--print(getmetatable(s1))--setmetatable(s1, {})local Window = {} -- create a namespace--create teh prototype with default values.Window.prototype = {x=0, y=0, width=100, height=100}Window.mt = {} -- create a metatable--declare the constructor functionfunction Window.new(o)setmetatable(o, Window.mt)return oendWindow.mt.__index = function(table, key)return Window.prototype[key]end--Window.mt.__index = Window.prototypew = Window.new {x=10, y=20}print(w.x)-- Tables with default valueslocal function setDefault(t, d)local mt = {__index = function() return d end}setmetatable(t, mt)endlocal tab = {x=10, y=20}print(tab.x, tab.z)setDefault(tab, 0)print(tab.x, tab.z)local mt = {__index = function(t) return t.___ end }local function setDefault(t, d)t.___ = dsetmetatable(t, mt)end-- Tracking table accesseslocal t = {} -- original table (created somewhere)-- keep a private access to the original tablelocal _t = t-- create proxyt = {}-- create metatablelocal mt = {__index = function(t, k)print("*access to element " .. tostring(k))return _t[k]end,__newindex = function(t, k, v)print("*update of element " .. tostring(k) .. " to " .. tostring(v))_t[k] = v -- update original tableend}setmetatable(t, mt)t[2] = "hello"print(t[2])-- Read-only tablesfunction readOnly(t)local proxy = {}local mt = {__index = t,__newindex = function(t, k, v)error("attempt to update a read-only table", 2)end}setmetatable(proxy, mt)return proxyenddays = readOnly {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}print(days[1]) --days[2] = "Noday"endlocal function objectTest()local Account = {balance = 0,new = function(self, o)o = o or {} -- create table is user does not provide onesetmetatable(o, self)self.__index = selfreturn oend,withdraw = function(self, v)if v>self.balance then error"insufficient funds" endself.balance = self.balance - vend,deposit = function(self, v)self.balance = self.balance + vend}local a = Account:new {balance = 0}a:deposit(100.00)print(a.balance)local b = Account:new()print(b.balance)b.balance = 123print(b.balance)b:withdraw(100)print(b.balance)print(a.balance)-- inheritancelocal SpecialAccount = Account:new({withdraw = function(self, v)if v - self.balance >= self:getLimit() thenerror"insufficient funds"endself.balance = self.balance - vend, getLimit = function(self) return self.limit or 0end})local s = SpecialAccount:new {limit=1000.00}s:deposit(100.00)s:withdraw(200.00)print("s:", s.balance)endlocal function main()languageTest();tableTest();objectTest();endmain()
- Lua学习之function
- Lua学习之function
- Lua学习笔记之function type
- lua学习笔记之Lua的function、closure和upvalue
- lua学习笔记之Lua的function、closure和upvalue
- Lua Function学习
- Lua基础之Function
- Lua 学习笔记之 function、closure和upvalue
- lua学习笔记--random function
- lua学习笔记---Function(函数)
- lua学习之--liu.lua
- lua function
- Lua function
- lua-function
- lua function
- boost学习之function
- boost学习之-function
- LUA学习之编译
- Visual C++ 6.0中显示行号的方法
- U盘提示格式化,只剩8M但又格式化不了的数据恢复教程
- 生命中的贵人
- 修改tomcat的默认编码
- php拾遗
- Lua学习之function
- Qt 正则表达式检测密码格式
- mm_struct
- Jquery的使用
- Inter company transaction flow types.
- 金融工程中的蒙特卡罗方法
- dedecms如何去掉底部power by dedecms 链接
- c语言学习
- android面试题总结加强版(二)