每日一Lua(4)-深入函数
1.函数是Lua中的第一值 在Lua中,函数能够像数字和字符串那样,存储在变量和table中,也能作为参数进行传递,也可以作为函数的返回值。 2.词法域 一个函数可以访问外部函数的变量。 3.匿名函数 函数与所有其他值一样都是匿名的,即他们都没有名称,我们可以把函数看成一个值。可以将它赋给某个变量。 foo=function ( x ) return 2*x end print(foo(2)) 4.函数作为参数传递 在table中有一个sort函数,接受一个table值和一和函数作为参数。例如: classmate={ {name="Jack",grade="90"},{name="Rose",grade="80"},{name="Tomas",grade="88"},{name="Mary",grade="60"} } foo=function () for k,val in ipairs(classmate) do print(val.name.."-"..val.grade) end end print("Before sort:") foo() print("SortByName:") table.sort(classmate,function(a,b) return(a.name)>b.name end) foo() print("SortByGrade:") table.sort(classmate,b) return(a.grade)>b.grade end) foo() 运行结果: 这时候匿名函数就体现了很好的便捷性。 再看一个例子,函数求导。 导数的定义就是(f(x+d)-f(x))/d,其中d趋于无穷小。下面是lua实现。 function derivative( f,delta ) delta=delta or 1e-4 return function(x) return(f(x+delta)-f(x))/delta end end c=derivative(math.sin) print(math.cos(10),c(10)) 个人感觉有点乱-- 5.闭合函数 一个计数器的例子: function newCounter() local i=0 return function() i=i+1 return i end end c1=newCounter() print(c1()) print(c1()) print(c1()) 对于newCounter中的匿名函数,i为“非局部变量”,用于保持一个计数器,在匿名函数调用i的时候,看似已经超出了范围,实际上Lua会以closure的概念来正确的处理这种情况。这就是闭包。简单的讲,一个closure就是一个函数加上该函数所需方位的所有“非局部的变量”。如果再次调用newCounter,它就会创建一个新的局部变量i,从而得到一个新的closure。 接着上面的程序,执行下面的语句: c2=newCounter() print(c2()) print(c2()) c1和c2为一个函数所创建的两个不同的closure,他们个字拥有局部变量i的独立实例。 6.非全局函数 非全局函数指的是把函数当作一般的变量,如整数,字符串。将其存储在table字段中和局部变量中。例如: Lib={} Lib.add=function(x,y) return x+y end Lib.mul=function(x,y) return x-y end print(Lib.add(1,2)) print(Lib.mul(3,100)) 还有一个递归调用的例子 --local fact=function(n) local function fact(n) if n==0 then return 1 else return n*fact(n-1) end end print(fact(100)) 注释的那一行是报错的写法,因为在递归调用的时候发现fact没有定义,后者是正确的。 7.正确的尾调用 尾调用类似于goto的函数调用,当一个函数调用的是另一个函数的最后的一个动作时,该调用才算尾调用。 例如,f在调用完g之后就再也无其他事情可做。 function f(x) <some operation> return g(x) end Lua中尾调用的机制就是在确定为尾调用之后,执行完尾调函数就不需要返回原函数了,程序也不需要保存任何关于该函数的栈信息,不耗费任何栈空间,在lua中称为尾调用消除。 尾调用的一个很大的应用就是有限状态机了,从这个状态跳到令一个状态,然后可以无穷跳,而不用考虑栈的溢出,是不是很棒! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |