lua深入理解函数
来源:互联网 发布:三星淘宝官方旗舰店 编辑:程序博客网 时间:2024/05/29 16:26
1.在lua中,函数是一种第一类值,具有特定的词法域。
第一类值指函数可以储存到变量中或table中,可以作为实参传递,可以作为实参传递给其他函数,还可以作为其他函数的返回值
词法域指一个函数可以嵌套到另一个函数中,内部函数可以访问外部函数的变量
函数与所有其他值一样都是匿名的,当讨论一个函数时,实际上是在讨论一个持有某函数的变量。构造函数时,我们会将函数赋予全局变量,但在某些特殊情况中,仍会需要用到匿名函数,例如table.sort()
从技术上讲,Lua中只有closure, 而不存在“函数”。因为,函数本身就是一种特殊的closure。
(closure)闭合函数:
function newCounter() --在这段代码中,匿名函数访问了一个“非局部变量”i,该变量 local i = 0 --用于保持一个计数器。初看上去,由于创建变量i的函数已经返回 return function() --所以以后每次调用匿名函数时,i都应是超出了作用范围的 i = i + 1 --但其实不然,Lua会以closure的概念来正确处理这种情况。 return i --简单的讲,一个closure就是一个函数加上该函数所需访问 end --的所有局部变量。如果再次调用newCounter(),那么它会创建end --一个新的局部变量i,从而也将得到一个新的closure。c1 = newCounter() print(c1()) --> 1print(c2()) --> 2c2 = newCounter()print(c2()) --> 1print(c1()) --> 3
在许多场合closure都是一种很有价值的工具。就像之前看到,它们可以作为sort这类高阶函数的参数。
closure对于那些创建其他函数的函数也很有价值,例如前例中的newCounter.
closure可以用于重新定义那些预定义的函数,如下面的例子利用closure限制文件的访问程序
local oldOpen = io.open local access_OK = function(filename, mode) <检查访问权限> end io.open = function(filename, mode) if access_OK(filename, mode) then return oldOpen(filename, mode) else return nil, "accsee denied" end end
2.函数存在table中的三种方法
lib = {}lib.foo = function(x,y) return x+y endlib.goo = function(x,y) return x-y endlib = { foo = function (x, y) return x+y end goo = function (x, y) return x-y end}lib = {}function lib.foo (x,y) return x+y endfunction lib.goo (x,y) return x-y end
3.定义递归局部函数注意点
local fact = function(n)if n == 0 then return 1 else return n*fact(n-1) --错误 endend编译到fact(n-1)时,局部的fact尚未定义完毕,此句调用的是一个全局的fact,可改为local factfact = function(n)...end
4.尾调用消除
什么是尾调用:一个函数调用是另一个函数的最后一个动作
function f(x) return g(x) end--当f调用完g后无事情可做,无需保存该函数的栈信息,称为尾调用消除function foo(n) if n > 0 then return foo(n-1) end --传入任何数字都不会造成栈溢出end
以下不是尾调用:
function f(x) g(x) end --调用完g后还需丢弃g返回的临时结果return g(x) + 1 --必须做一次加法return x or g(x) --必须调整为一个返回值return (g(x)) --必须调整为一个返回值只有“return <func>(<args>)”这样的调用形式才算是一条尾调用,lua会在调用前对func和其参数求值例如:return x[i].foo(x[j] + a*b, i+j) 是一条尾调用
5.迭代器
迭代器是一种可以遍历一种集合中所有元素的机制,在lua中,通常将迭代器表示为函数。
每调用一次函数,即返回集合中的下一个元素,closure对于迭代过程中的状态保持提供了极佳的支持
下面是一个简单的示例
function values(t) local i = 0return function() i = i+1;return t[i] endend--调用values产生一个迭代器,调用迭代器返回下一个值。泛型for在内部保存了迭代器函数。
下面看一个更高级的示例
function allwords() local line = io.read() --当前行 local pos = 1 --一行中的当前位置 return function() --迭代器函数 while line do --若为有效的行内容就进入循环 local s,e = string.find(line, "%w+", pos) if s then --是否找到一个单词 pos = e+1 --该单词的下一个位置 return string.sub(line, s, e) --返回该单词 else line = io.read() --没有找到单词,尝试下一行 pos = 1 --在第一个位置上重新开始 end end return nil --没有其余行,遍历结束 endend for word in allwords() do print(word)end
上述迭代器在每个新的循环都创建一个新的closure,泛型for可用自身来保持迭代器状态
阅读全文
0 0
- lua深入理解函数
- 深入理解lua中的"."和":"
- Lua笔记-6深入函数
- (4)LUA程序设计-函数及深入理解(function)
- 深入理解JavaScript函数
- 深入理解sizeof()函数
- 深入理解指针函数
- 深入理解指针函数
- sizeof()函数深入理解
- 深入理解指针函数
- 深入理解指针函数
- 深入理解指针函数
- 深入理解指针函数
- 深入理解指针函数
- 深入理解指针函数
- 深入理解指针函数
- 深入理解指针函数
- 深入理解指针函数
- 在table中使显示的文本显示一行后其余用省略号表示
- 利用栈求表达式的值(数据结构课程设计)
- 如何选择python版本
- opencv--003改变图片的对比度和亮度
- log4j代码优化
- lua深入理解函数
- FindBugs 简介
- Maven工程引入JSON依赖JAR包
- OTP原理及实现
- node
- android缓存数据路径集合
- fprintf写文件
- Android 网络超时
- 如何把别人项目代码修改后 提交到github