每日一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,function(a,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中称为尾调用消除。

尾调用的一个很大的应用就是有限状态机了,从这个状态跳到令一个状态,然后可以无穷跳,而不用考虑栈的溢出,是不是很棒!


你可能感兴趣的:(每日一Lua(4)-深入函数)