Lua的奇妙冒险1初窥(下半部)
上一篇我们了解了Lua的基本结构和基础类型,下面我将介绍Lua的表达式、函数还有参数相关的问题。
Lua的函数定义和其他常见脚本语言相似
>function triple(num)
>> return 3 * num
>>end
>>
=triple(2)
6(结果)
但严格来说,函数的名称并不是必需的,以上的代码可以转化下面的也可以的。
> =(function(num) return 3 * num end) (2)
6
在Lua的世界里函数是一等公民(高高在上捏);它们和其他值一样,可以给变量赋值,可以当成参数传递给其他函数,也可以保存在数据结构中。
eg.
>function call_twice(f)
>> ff = function (num)
>> return f(f(num))
>>end
>>return ff
>>end
>
>function triple(n)
>>return n * 3
>>end
>
>times_nine = call_twice(triple)
>
=times_nine(5)
45(结果)
//写了一个叫做call_twice()的函数,它收到一个叫f()的参并且返回一个叫ff()的函数,那么ff会调用f2次
Lua的一个强大功能是把函数当作数据来用,同时是Lua简洁性的重要来源。
灵活的参数
有些的语言在我们调用函数时,因传入的参数太少而报错,而Lua不会,它会简单的把所有未传入的参数赋值为nil。
>function print_characters(friend, foe)
>>print('Friend and foe')
>>print(friend)
>>print(foe)
>>end
>print_characters('Marcus','Belloq')
Friend and foe
Marcus
Belloq
>print_characters('Marcus')
Friend and foe
Marcus
nil
而多余的参数会被省略掉
>print_characters('Marcus','Belloq','unuesed')
Friend and foe
Marcus
Belloq
你也可以写可变参数的函数(函数的参数数量是不固定的),只要把函数的最后一个参数标为省略号即可(
...)。
Lua函数有另一个很方便的特性,那就是尾递归化优化。当一个递归函数对自己的调用是其所做的最后一件事市,该函数就会被尾递归优化处理:
function reverse(s,t)
if #s<1 then return t end
first = string.sub(s,1,-1)
rest = string.sub(s,2,-1)
return reverse(rest,first .. t)
end
large = string.rep('hello',5000)
print(reverse(large,''))
//以上的函数会把有些其他语言卡死;比如JavaScript引擎在执行以上代码时会发生栈溢出。而Lua可以正确地把尾递归优化成goto语句,并完成计算。
多个函数的返回值
和参数类似,函数的返回值也可以有很多个,你可以选择使用所有的返回值,或者忽略其中一部分:
>function weapons()
>>return'bullwhip','revolver'
>>end
>
>w1 = weapons()
>print(w1)
bullwhip
>
>w1,w2 =weapons()
>print(w1)
bullwhip
>print(w2)
revolver
>
>w1,w2,w3 = weapons()
>print(w1)
bullwhip
>print(w2)
revolver
>print(w3)
nil
和参数的规则一样,未使用的返回值会被忽略掉,未使用到的变量会被赋值为nil。
具名参数
Lua不像Python或者Ruby一样在语法级别方面支持具名函数。不过可以通过table当成参数传递给函数来达到类似的效果:
>function popcorn_prices(table)
>>print('A medium popcorn costs '.. table.medium)
>>end
>
>popcorn_prices{small=5.00
>>medium=7.00
>>jumbo=15.00}
A medium popcorn costs 7
//该例中,大括号中爆米花大小和价格就是table(在这里Lua允许我们不给函数调用加小括号)。函数体可以通过点号读取table中的某一个特定的值(table.medium)
你可以通过函数构造出很多东西,甚至是一门编程语言!
控制流程
Lua内建的流程控制包括if、两种for循环,以及while循环。
if语句可以对应一个else甚至是多个,还有elseif。和其他语言不同的是Lua无需返回值,只需要你把它打印出来即可
>film= 'skull'
>
>if film == 'Raiders' then
>>print('Good')
>>elseif film == 'Temple' then
>>print('Meh')
>>elseif film =='Crusade'
>>print('Great')
>>else
>>print('Huh?')
>>end
for循环遍历一系列的数值(步进值可选)
>for i = 1,5 do
>>print(i)
>>end
1 2 3 4 5
>for i = 1,5,2 do
>>print(i)
>>end
1 3 5
你也可以使用for循环来遍历集合(第二天我们讲table时会再讲)
最后一个内建流程控制是while循环以及它的近亲repeat循环
>while math.random(100) < 50 do
>>print('Tails;flipping again')
>>end
Tails;flipping again
Tails;flipping again
Lua不会限制你仅能用这三个。如果你把它们和高阶函数结合,就可以构造出你程序需要的任意流程控制
变量
我们最后一个讲的是变量,在前面我们粗略的带过了变量,我们现在细谈一下变量。
Lua的变量默认是全局的
>function hypotenuse(a,b)
>>a2 = aa
>>b2 = bb
>>return math.sqrt(a2+b2)
>>end
>>=hypotenuse(3,4)
5>
=a2
9
或许你希望a2这个临时变量不会漏在函数之外。我们只要在局部变量的声明前加上local关键字就好了
>function hypotenuse(a,b)
>>local a2 = aa
>>local b2 = bb
>>return math.sqrt(a2+b2)
>>end
如果我们不小心创建出全局变量,可以用Lua的table来实现这一点。
这就是第一天的最后了,我改了很久,尽量用通俗易读的方式来表达书中略有晦涩的地方,应该是量大管饱,也是对不起鸽了几天,希望能够关注一下我,过几天做第二天喵~o( =∩ω∩= )m
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)