返回介绍

2.5.9 - 函数定义

发布于 2019-08-25 13:16:35 字数 2095 浏览 953 评论 0 收藏 0

函数定义的语法如下:

	function ::= function funcbody
	funcbody ::= `(´ [parlist1] `)´ block end

另外定义了一些语法糖简化函数定义的写法:

	stat ::= function funcname funcbody
	stat ::= local function Name funcbody
	funcname ::= Name {`.´ Name} [`:´ Name]

这样的写法:

 function f () body end

被转换成

 f = function () body end

这样的写法:

 function t.a.b.c.f () body end

被转换成

 t.a.b.c.f = function () body end

这样的写法:

 local function f () body end

被转换成

 local f; f = function () body end

注意,并不是转换成

 local f = function () body end

(这个差别只在函数体内需要引用 f 时才有。)

一个函数定义是一个可执行的表达式, 执行结果是一个类型为 function 的值。 当 Lua 预编译一个 chunk 的时候, chunk 作为一个函数,整个函数体也就被预编译了。 那么,无论何时 Lua 执行了函数定义, 这个函数本身就被实例化了(或者说是关闭了)。 这个函数的实例(或者说是 closure(闭包)) 是表达式的最终值。 相同函数的不同实例有可能引用不同的外部局部变量, 也可能拥有不同的环境表。

形参(函数定义需要的参数)是一些由实参(实际传入参数)的值初始化的局部变量:

	parlist1 ::= namelist [`,´ `...´] | `...´

当一个函数被调用, 如果函数没有被定义为接收不定长参数,即在形参列表的末尾注明三个点 ('...'), 那么实参列表就会被调整到形参列表的长度, 变长参数函数不会调整实参列表; 取而代之的是,它将把所有额外的参数放在一起通过变长参数表达式传递给函数, 其写法依旧是三个点。 这个表达式的值是一串实参值的列表,看起来就跟一个可以返回多个结果的函数一样。 如果一个变长参数表达式放在另一个表达式中使用,或是放在另一串表达式的中间, 那么它的返回值就会被调整为单个值。 若这个表达式放在了一系列表达式的最后一个,就不会做调整了(除非用括号给括了起来)。

我们先做如下定义,然后再来看一个例子:

 function f(a, b) end
 function g(a, b, ...) end
 function r() return 1,2,3 end

下面看看实参到形参数以及可变长参数的映射关系:

 CALL PARAMETERS
 
 f(3) a=3, b=nil
 f(3, 4) a=3, b=4
 f(3, 4, 5) a=3, b=4
 f(r(), 10) a=1, b=10
 f(r()) a=1, b=2
 
 g(3) a=3, b=nil, ... --> (nothing)
 g(3, 4) a=3, b=4, ... --> (nothing)
 g(3, 4, 5, 8) a=3, b=4, ... --> 5 8
 g(5, r()) a=5, b=1, ... --> 2 3

结果由 return 来返回(参见 §2.4.4)。 如果执行到函数末尾依旧没有遇到任何 return 语句, 函数就不会返回任何结果。

冒号语法可以用来定义方法, 就是说,函数可以有一个隐式的形参 self。 因此,如下写法:

 function t.a.b.c:f (params) body end

是这样一种写法的语法糖:

 t.a.b.c.f = function (self, params) body end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文