Lua中函数的几个特别之处探究_Lua

没想到距离上一篇基础补充已经过了1年多了,最近准备捡回Lua,把基础都补补,今天来聊聊Lua的函数吧~

0.环境

我突然对Lua又大感兴趣的最主要原因是,Cocos Code IDE开始浮出水面了,它是Cocos2d-x官方出的一款专门针对Cocos2d-x+Lua或JS的IDE,试着用了,虽然不能说很完美,但,很值得期待。

所以,本文使用的Lua编辑器就选它了,大家就随意吧~

1.扫盲——Lua的函数

Lua要创建和调用函数都十分简单,如代码:

复制代码 代码如下:

function mutou()
print("这绝对不是广告:www.jb51.net");
end

这就创建了一个函数了,调用函数也十分简单:

复制代码 代码如下:

mutou();

然后运行,就能看到输出了,print也是一个函数,唉,不多唠叨了。

2.扫盲——函数的参数

刚刚的mutou函数,我们修改一下参数,如代码:

复制代码 代码如下:

function mutou(name, age)
print(name);
print(age);
end

我们给mutou添加两个参数,一个是name,代表名字,一个是age,代表年龄。
顺便一提,Lua是没有变量类型这一说法的,变量会根据赋予的值而展现出不一样的类型。
 
我们试试这样调用mutou函数:

复制代码 代码如下:

mutou("木头", 25);

然后运行,输出如下:

复制代码 代码如下:

[LUA-print] 木头
[LUA-print] 25

很正常,我喜欢~

3.海量的心——函数参数个数自适应

Lua的函数心胸比较宽广,对于我们传递进去的参数,全部都会忍受,但,它会按照它的规则进行筛选。
 
继续刚刚那个mutou函数,我们试试这样调用:

复制代码 代码如下:

mutou("木头");

少给了一个参数,但,这和C++或者Java等语言不一样,它不会造成编译错误,仍然可以正常运行。输出如下:

复制代码 代码如下:

[LUA-print] 木头
[LUA-print] nil

对于缺少的参数,它会自动用nil来代替。
 
再然后,既然可以少给参数,那自然也可以多给参数了,试试这样调用:

复制代码 代码如下:

mutou("木头", 25, "旁白", 45);

(小若:你才45岁!你全身细胞都是45岁!)
输出如下:

复制代码 代码如下:

[LUA-print] 木头
[LUA-print] 25

结果自然是,多出参数会被舍去。
至于这是好事还是坏事,就看是谁使用了~

4.多重返回值

没错,Lua似乎把我们想要的能偷懒的所有事情都给想到了,并且给实现了。

Lua的函数支持返回多个值,继续修改mutou函数,如下:

复制代码 代码如下:

function mutou(name, age)
return name, age;
end

把传进去的两个参数又给return回来了,试试这样调用:

复制代码 代码如下:

local name = mutou("木头", 25);
print(name);

调用mutou函数,并且用一个变量保存返回值,输出结果为:

复制代码 代码如下:

[LUA-print] 木头

 
因为我们只用了一个变量来保存返回值,所以即使函数返回了两个值,我们也只能获取到一个,要想获取到两个值,就十分简单了,如下:

复制代码 代码如下:

local name, age = mutou("木头", 25);
print(name .. ":" .. age);

输入结果如下:

复制代码 代码如下:

[LUA-print] 木头:25

又顺便一提,用符号“..”可以连接字符串,这里就不多说了~
 
返回值和参数一样,如果我们尝试用三个变量去获取函数返回值,也不会造成编译错误,如下:

复制代码 代码如下:

local name, age, hehe = mutou("木头", 25);
print(name .. ":" .. age);
print(hehe);

输入如下:

复制代码 代码如下:

[LUA-print] 木头:25
[LUA-print] nil

对于多出的变量,会赋予nil值,虽然这不会造成编译错误,但是也可能会造成运行时错误。

比如,用“..”符号去连接nil值,就会报错。

5.多重返回值的特点1——必须是表达式的最后一个元素

对于有多个返回值的函数,不一定所有情况下都能返回多个值。

先来看这样一种特别的情况,仍然是刚刚的mutou函数,我们这样调用:

复制代码 代码如下:

local a, b, c = "first", mutou("木", 25);
print(a);
print(b);
print(c);

输出结果如下:

复制代码 代码如下:

[LUA-print] first
[LUA-print] 木
[LUA-print] 25

没错,Lua的赋值语句是支持逗号表达式的(也就是用多个值给多个变量赋值),排在前面的值自然就优先赋给变量,所以变量a的值就是”first”。
不过,这不是重点~(小若:那你还说个毛线啊!)
 
重点是,我们把顺序调换一下,如下:

复制代码 代码如下:

local a, b, c =  mutou("木", 25), "first";
print(a);
print(b);
print(c);

输出结果会出乎大家的意料:

复制代码 代码如下:

[LUA-print] 木
[LUA-print] first
[LUA-print] nil

没错,mutou函数的返回值变成只有一个了,这就是函数的特点之一:如果函数的调用不是在表达式的最后一个元素,则,最多只返回一个值。
 
什么?还不够清晰吗?那再来举个粒子(小若:粒子你个头啊!)
我们这样调用函数…额,那个,我们继续下一条内容。(小若:举不出例子那你刚刚还激动个毛线啊!)

6.多重返回值的特点2——强制返回一个值

某些情况下,我们可能会对于一个函数感到厌烦,没错,为什么你总是返回多个值?!(小若:还不是你自己写的函数吗!)
 
如果想让某个函数强制只返回一个值,可以这么做:

复制代码 代码如下:

local a, b = (mutou("木", 25));
print(a);
print(b);

输入结果如下:

复制代码 代码如下:

[LUA-print] 木
[LUA-print] nil

 
我们只需要在函数调用时,把函数调用放在括号中就可以了。

7.名字参数/具名实参/named arguments

最后,我们来看看比较实用的一种函数参数——名字参数。

其实“名字参数”是我自己的叫法,《Lua程序设计》第二版中是称之为“具名实参”,但我看到英文单词以及用法之后,我还是比较倾向于称之为“名字参数”。
 
先来问大家一个问题,我们刚刚一直在讨论的mutou函数,有多少个参数,不要回去看,1秒钟内回答~(小若:2个!)

第二个问题,mutou函数的age和name参数哪个在前哪个在后?0.001秒内回答!(小若:回答你个头啊!)
 
没错,我们有时候并不记得一个函数的参数顺序,倒底age是第一个参数呢,还是name是第二个参数?(小若:好像哪里不对…)
 
于是,具名实参就派上用场了。
我们修改一下mutou函数:

复制代码 代码如下:

function mutou(args)
return args.name, args.age;
end

现在mutou函数的参数变成了一个table,它要求table中包含name和age两个值。
 
于是,我们调用mutou函数的方式就变成了这样:

复制代码 代码如下:

local args = {name = "木", age = 25};
print(mutou(args));

没错,传递一个table变量给mutou函数就可以了,由于函数在取参数值的时候,是根据table的key值来获取的,根本就不需要考虑参数顺序,这就解决了我们刚刚所说的顺序问题了。

8.结束

好了,关于函数的基础特性,就这么多了,当然,还有一个变长参数我没有提到,因为这好像没什么好提的~
 
最近我在计划坚持一件事情,那就是:晚上不写游戏,哪怕遇到让人兴奋的Bug。
我想把晚上的时间都拿来充电,我的基本功实在是不够用了,有点摇摇欲坠的感觉。
 
近期是计划把《Lua程序设计》这本书过一遍,希望能坚持~
计划是每晚花一小时看书,花一小时整理教程。
 
今天是第一天,很累,写教程比写游戏累多了。
有句什么话来着,永远不要让自己处于舒适的范围里,好吧,坚持…
(小若:用个毛线的省略号啊!用感叹号啊!这样才代表你有决心…)
 
我说,小若,那为什么你最后也用了省略号…

时间: 2024-07-29 09:47:50

Lua中函数的几个特别之处探究_Lua的相关文章

Lua中函数与面向对象编程的基础知识整理_Lua

函数 1. 基础知识调用函数都需要写圆括号,即使没有参数,但有一种特殊例外:函数若只有一个参数且参数是字面字符串或table构造式,则圆括号可有可无,如dofile 'a.lua',f{x=10, y=20}. Lua为面向对象式的调用提供冒号操作符的特殊语法,如o.foo(o, x)等价于o:foo(x).和Javascript类似,调用函数时提供的实参数量可以与形参数量不同,若实参多了则舍弃,不足则多余的形参初始化为nil. 1.1 多重返回值 Lua允许函数返回多个结果,函数返回如retu

Lua中的for循环和迭代器的秘密探究_Lua

上一篇我们介绍了,可以使用for循环来完成迭代器的调用,十分简洁. 那么,具体这for循环做了什么呢?我当然没有去看源码,我只是看书而已. 资料来源于<Lua程序设计>第二版,如果这本书的内容没有错的话,那么,本篇文章理论上也不会有错~ 1.返回两个值的迭代器 pairs是能遍历table的key和value的,而我们之前写的dieDaiQi函数只能返回value. 所以,我们要改改dieDaiQi函数,如下: 复制代码 代码如下: function dieDaiQi(t)     local

Lua中的模块(module)和包(package)详解_Lua

前言 从Lua5.1版本开始,就对模块和包添加了新的支持,可是使用require和module来定义和使用模块和包.require用于使用模块,module用于创建模块.简单的说,一个模块就是一个程序库,可以通过require来加载.然后便得到了一个全局变量,表示一个table.这个table就像是一个命名空间,其内容就是模块中导出的所有东西,比如函数和常量,一个符合规范的模块还应使require返回这个table.现在就来具体的总结一下require和module这两个函数. require函

解析Lua中的全局环境、包、模块组织结构_Lua

模块就是一个程序库,而包是一系列模块.Lua中可以通过require来加载模块,然后得到一个全局变量表示一个table.Lua将其所有的全局变量保存在一个被称为"环境"的常规table中.本文首先介绍环境的一些实用技术,然后介绍如何引用模块及编写模块的基本方法. 1. 环境Lua将环境table保存在一个全局变量_G中,可以对其访问和设置.有时我们想操作一个全局变量,而它的名称却存储在另一个变量中,或者需要通过运行时的计算才能得到,可以通过value = _G[varname]来获得动

Lua中使用table实现的其它5种数据结构_Lua

lua中的table不是一种简单的数据结构,它可以作为其他数据结构的基础,如:数组,记录,链表,队列等都可以用它来表示. 1.数组 在lua中,table的索引可以有很多种表示方式.如果用整数来表示table的索引,即可用table来实现数组,在lua中索引通常都会从1开始. 复制代码 代码如下: --二维数组 n=10 m=10 arr={} for i=1,n do      arr[i]={}    for j=1,m do       arr[i][j]=i*j    end end f

举例简介Lua中函数的基本用法_Lua

复制代码 代码如下: function fib(n)   if n < 2 then return 1 end   return fib(n - 2) + fib(n - 1) end 复制代码 代码如下: -- 支持闭包及匿名函数: function adder(x)   -- 调用adder时,会创建用于返回的函数,并且能记住变量x的值:   return function (y) return x + y end end a1 = adder(9) a2 = adder(36) print

Lua中__index和__newindex之间的沉默与合作_Lua

因为不想在一篇文章里挤太多知识点,所以,有些小知识点就集合到这样的文章里吧~ 1.沉默技能--拒绝__index和__newindex效果 虽然__index和__newindex是很好用的功能,但是,有时候我们又希望很纯粹地去调用table或者给table赋值. 那,这时候怎么办?给table重新设置一个元表?不,这个做法很糟糕~ 于是,体贴的Lua又给我们提供了这样的调用方式,如下代码: 复制代码 代码如下:     local smartMan = {         name = "no

Lua中的loadfile、dofile、require详解_Lua

本来今天不应该讨论这几个函数的,不过,为了凑字数..不,为了方便以后的文章,还是要谈谈这几个基础函数的~ 1.loadfile--只编译,不运行 loadfile故名思议,它只会加载文件,编译代码,不会运行文件里的代码. 比如,我们有一个hellofile.lua文件: 复制代码 代码如下: print("hello"); function hehe() print("hello"); end 这个文件里有一句代码,和一个函数.试试用loadfile加载这个文件,如

Lua中遍历数组和table的4种方法_Lua

方法一,可以用for来遍历: 复制代码 代码如下: do      table_week = {      "w",      "e",      "r",      "t",      "y",      "u",      "i",      }        for i = 1, #table_week do          print(table_week[