gpt4 book ai didi

Lua中的函数(function)、可变参数、局部函数、尾递归优化等实例讲解

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Lua中的函数(function)、可变参数、局部函数、尾递归优化等实例讲解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

1、函数 。

在Lua中,函数是作为"第一类值"(First-Class Value),这表示函数可以存储在变量中,可以通过参数传递给其他函数,或者作为函数的返回值(类比C/C++中的函数指针),这种特性使Lua具有极大的灵活性。   Lua对函数式编程提供了良好的支持,可以支持嵌套函数。   另外,Lua既可以调用Lua编写的函数,还可以调用C语言编写的函数(Lua所有的标准库都是C语言写的)。   定义一个函数 。

复制代码 代码如下:

function hello()
print('hello')
end

  。

hello函数不接收参数,调用:hello(),虽然hello不接收参数,但是还可以可以传入参数:hello(32)   另外如果只传递一个参数可以简化成functionname arg的调用形式(注意数值不行) 。

复制代码 代码如下:

> hello '3'
hello
> hello {}
hello
> hello 3
stdin:1: syntax error near '3'

  另外对变量名也不适用 。

复制代码 代码如下:

> a = 21
> print a
stdin:1: syntax error near 'a'

  另外,Lua函数不支持参数默认值,可以使用or非常方便的解决(类似Javascript) 。

复制代码 代码如下:

> function f(n)
>> n = n or 0
>> print(n)
>> end
> f()
0
> f(1)
1

  。

Lua支持返回多个值,形式上非常类似Python:

复制代码 代码如下:

> function f()
>> return 1,2,3
>> end
> a,b,c = f()
> print(a .. b .. c)
123

  函数调用的返回值可以用于table:

复制代码 代码如下:

> t = {f()}
> print(t[1], t[2], t[3])
1        2        3

  可见,f()返回的三个值分别称为table的3个元素,但是情况并不总是如此:

复制代码 代码如下:

> t = {f(), 4}
> print(t[1], t[2], t[3])
1        4        nil

这次,f()返回的1,2,3只有1称为table的元素; 。

复制代码 代码如下:

> t = {f(), f()}
> print(t[1], t[2], t[3], t[4], t[5])
1        1        2        3        nil

  总之:只有最后一项会完整的使用所有返回值(假如是函数调用)。   对于无返回值的函数,可以使用(f())的形式强行返回一个值(nil) 。

复制代码 代码如下:

> function g()
>> end
> print(g())
 
> print((g()))
nil

实际上,(f())形式的调用返回一个且只返回一个值 。

复制代码 代码如下:

> print((f()))
1
> print(f())
1        2        3

  。

2、变长参数 。

Lua支持编程参数,使用简单(借助于table、多重赋值) 。

复制代码 代码如下:

> function f(...)
for k,v in ipairs({...}) do
print(k,v)
end
end
> f(2,3,3)
1        2
2        3
3        3

使用多重赋值的方式 。

复制代码 代码如下:

> function sum3(...)
>> a,b,c = ...
>> a = a or 0
>> b = b or 0
>> c = c or 0
>> return a + b +c
>> end
> =sum3(1,2,3,4)
6
> return sum3(1,2)
3

通常在遍历变长参数的时候只需要使用{…},然而变长参数可能会包含一些nil;那么就可以用select函数来访问变长参数了:select('#', …)或者 select(n, …) 。

  。

select('#', …)返回可变参数的长度,select(n,…)用于访问n到select('#',…)的参数 。

复制代码 代码如下:

> =select('#', 1,2,3)
3
> return select('#', 1,2, nil,3)
4
> =select(3, 1,2, nil,3)
nil        3
> =select(2, 1,2, nil,3)
2        nil        3

注意:Lua5.0中没有提供…表达式,而是通过一个隐含的局部table变量arg来接收所有的变长参数,arg.n表示参数的个数; 。

  。

3、函数式编程 。

函数做一个First-Class Value可以赋值给变量,用后者进行调用 。

复制代码 代码如下:

> a = function() print 'hello' end
> a()
hello
> b = a
> b()
hello

匿名函数 。

复制代码 代码如下:

> g = function() return function() print 'hello' end end
> g()()
hello

函数g返回一个匿名函数;   闭包是函数式编程的一种重要特性,Lua也支持 。

复制代码 代码如下:

> g = function(a) return function() print('hello'.. a); a = a + 1 end end
> f = g(3)
> f()
hello3
> f()
hello4

  。

4、局部函数 。

局部函数可以理解为在当前作用域有效的函数,可以用local变量来引用一个函数:

复制代码 代码如下:

> do
>> local lf = function() print 'hello' end
>> lf()
>> end
hello
> lf()
stdin:1: attempt to call global 'lf' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: in ?

  。

需要注意的是,对于递归函数的处理 。

复制代码 代码如下:

> do
local lf = function(n)
if n <= 0 then
return
end
print 'hello'
n = n -1
lf(n)
end
lf(3)
end
hello
stdin:8: attempt to call global 'lf' (a nil value)
stack traceback:
stdin:8: in function 'lf'
stdin:9: in main chunk
[C]: in ?

而应该首先声明local lf, 在进行赋值 。

复制代码 代码如下:

do
local lf;
lf = function(n)
if n <= 0 then
return
end
print 'hello'
n = n -1
lf(n)
end
lf(3)
end
hello
hello
hello

Lua支持一种local function(…) … end的定义形式:

复制代码 代码如下:

> do
local function lf(n)
if n <= 0 then
return
end
print 'hello'
n = n -1
lf(n)
end
lf(3)
end
hello
hello
hello
> lf(3)
stdin:1: attempt to call global 'lf' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: in ?

  。

5、尾调用 。

所谓尾调用,就是一个函数返回另一个函数的返回值:

复制代码 代码如下:

function f()

return g()
end

  因为调用g()后,f()中不再执行任何代码,所以不需要保留f()的调用桟信息;Lua做了这样的优化,称为"尾调用消除",g()返回后,控制点直接返回到调用f()的地方。   这种优化对尾递归非常有益,通常递归意味着调用桟的不断增长,甚至可能造成堆栈溢出;而尾递归提供了优化条件,编译器可以优化掉调用桟。   下面的递归函数没有使用尾递归,而参数为大数时,堆栈溢出:

复制代码 代码如下:

> function f(n)
>> if n <= 0 then
>> return 0
>> end
>> a = f(n-1)
>> return n * a
>> end
> f(10000000000)
stdin:5: stack overflow
stack traceback:
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
...
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:1: in main chunk
[C]: in ?

优化为尾递归 。

复制代码 代码如下:

function f(n, now)
if n <= 0 then
return now
end
 
return f(n-1, now*n)
end
f(10000000000, 1)

运行n久也无堆栈溢出; 。

  。

最后此篇关于Lua中的函数(function)、可变参数、局部函数、尾递归优化等实例讲解的文章就讲到这里了,如果你想了解更多关于Lua中的函数(function)、可变参数、局部函数、尾递归优化等实例讲解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com