Lua 函数使用的完整指南

在 Lua 中,函数是一等公民(First-Class Citizen),这意味着函数可以像其他值一样被赋值、传递和操作。以下是 Lua 函数定义的完整指南,涵盖基础语法、高级特性、设计模式及性能优化。


在Lua 中,函数定义的完整指南—目录

  • 一、基础语法
    • 1. 函数声明
    • 2. 匿名函数
  • 二、核心特性
    • 1. 多返回值
    • 2. 变参函数(Variadic Function)
    • 3. 函数作为返回值
  • 三、进阶特性
    • 1. 闭包(Closure)
    • 2. 尾调用优化(Tail Call Optimization)
    • 3. 高阶函数(Higher-Order Function)
  • 四、函数属性与元编程
    • 1. 函数属性
    • 2. 元表与函数钩子
  • 五、性能优化指南
    • 1. 避免闭包滥用
    • 2. 内联小函数
    • 3. 使用局部函数
  • 六、设计模式与最佳实践
    • 1. 策略模式
    • 2. 工厂模式
    • 3. 观察者模式
  • 七、调试与元信息
    • 1. 获取函数信息
    • 2. 函数重载(模拟)
  • 八、常见问题与解决方案
    • 问题1:函数参数过多时的处理
    • 问题2:递归深度过大导致栈溢出


一、基础语法

1. 函数声明

-- 基础语法
function add(a, b)return a + b
end-- 调用
print(add(3, 5))  -- 输出 8

2. 匿名函数

-- 无名称的函数(常用于回调)
local function factorial(n)return n == 0 and 1 or n * factorial(n-1)
end-- 将函数赋值给变量
local square = function(x) return x * x end
print(square(4))  -- 输出 16

二、核心特性

1. 多返回值

function divide_and_remainder(a, b)return math.floor(a / b), a % b
endlocal quotient, remainder = divide_and_remainder(10, 3)
print(quotient, remainder)  -- 输出 3 1

2. 变参函数(Variadic Function)

-- 使用 ... 接收任意数量参数
function sum(...)local total = 0for _, v in ipairs({...}) dototal = total + vendreturn total
endprint(sum(1,2,3,4))  -- 输出 10

3. 函数作为返回值

function make_adder(x)return function(y)return x + yend
endlocal add5 = make_adder(5)
print(add5(3))  -- 输出 8

三、进阶特性

1. 闭包(Closure)

闭包是函数与其词法环境的组合,可捕获外部变量:

function counter()local count = 0return function()count = count + 1return countend
endlocal c = counter()
print(c())  -- 1
print(c())  -- 2

2. 尾调用优化(Tail Call Optimization)

尾调用不会增加调用栈深度,防止栈溢出:

function factorial(n, acc)acc = acc or 1if n == 0 then return acc endreturn factorial(n-1, n*acc)  -- 尾递归优化
endprint(factorial(5))  -- 输出 120

3. 高阶函数(Higher-Order Function)

函数作为参数或返回值:

-- map 函数
function map(t, fn)local result = {}for _, v in ipairs(t) dotable.insert(result, fn(v))endreturn result
endlocal numbers = {1,2,3,4}
local squares = map(numbers, function(x) return x*x end)
print(table.unpack(squares))  -- 输出 1 4 9 16

四、函数属性与元编程

1. 函数属性

function greet(name)return "Hello, " .. name
endgreet.__call = function(self, ...)return self.name .. ", " .. ...
endsetmetatable(greet, { __call = function(f, name) return "Hi, "..name end })print(greet("Alice"))  -- 输出 Hi, Alice

2. 元表与函数钩子

-- 统计函数调用次数
local call_counts = {}
local function hook(func)return function(...)call_counts[func] = (call_counts[func] or 0) + 1return func(...)end
endlocal function add(a, b)return a + b
endadd = hook(add)
add(1,2)
add(3,4)
print(call_counts[add])  -- 输出 2

五、性能优化指南

1. 避免闭包滥用

-- 低效写法:频繁创建闭包
for i = 1, 1000 dolocal function fn() return i end  -- 每次循环都创建新闭包
end-- 优化写法:使用局部变量捕获
for i = 1, 1000 dolocal i_local = ilocal function fn() return i_local end
end

2. 内联小函数

-- 频繁调用的简单函数可内联
-- 优化前
local function square(x) return x*x end
for i = 1, 1e6 dosquare(i)
end-- 优化后
for i = 1, 1e6 dolocal x = i*i  -- 直接展开计算
end

3. 使用局部函数

-- 全局函数查找较慢
function global_fn() end-- 优化:优先使用局部函数
local local_fn = function() end

六、设计模式与最佳实践

1. 策略模式

local strategies = {add = function(a,b) return a+b end,multiply = function(a,b) return a*b end
}function calculate(operation, a, b)return (strategies[operation] or strategies.add)(a, b)
endprint(calculate("multiply", 3,4))  -- 输出 12

2. 工厂模式

local function create_user(name, age)return {name = name,age = age,greet = function(self)print("I'm", self.name)end}
endlocal alice = create_user("Alice", 30)
alice:greet()  -- 输出 I'm Alice

3. 观察者模式

local function observable()local listeners = {}return setmetatable({}, {__newindex = function(t,k,v)rawset(t, k, v)for _, listener in ipairs(listeners) dolistener(k, v)endend,add_listener = function(t, listener)table.insert(listeners, listener)end})
endlocal obj = observable()
obj:add_listener(function(key, value)print("Property changed:", key, value)
end)
obj.x = 10  -- 触发监听器输出

七、调试与元信息

1. 获取函数信息

function example(a, b)return a + b
endprint(debug.getinfo(example).name)  -- 输出 "example"
print(debug.getupvalue(example, 1))  -- 查看闭包的上层变量(若有)

2. 函数重载(模拟)

local function overloaded(fn)local cache = {}return function(...)local key = table.concat({...}, "|")if not cache[key] thencache[key] = fn(...)endreturn cache[key]end
endlocal function process(a, b)return a + b
endlocal process_overloaded = overloaded(process)
print(process_overloaded(1,2))  -- 计算并缓存
print(process_overloaded(1,2))  -- 直接返回缓存结果

八、常见问题与解决方案

问题1:函数参数过多时的处理

-- 使用表传递可选参数
function config(options)local defaults = {width=800, height=600}for k, v in pairs(options) dodefaults[k] = vendreturn defaults
endlocal cfg = config({height=400})
print(cfg.width, cfg.height)  -- 输出 800 400

问题2:递归深度过大导致栈溢出

-- 尾递归优化版本
function fibonacci(n, a, b)a = a or 0b = b or 1if n == 0 then return a endif n == 1 then return b endreturn fibonacci(n-1, b, a+b)
endprint(fibonacci(1000))  -- 不会导致栈溢出

通过掌握这些函数特性与模式,你可以编写出高效、灵活的 Lua 代码。对于复杂场景,建议结合元编程和设计模式,同时注意性能优化细节。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/75200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用StockTV API对接印度金融市场数据全指南:K线、实时行情与IPO新股

一、印度金融市场数据特点 印度作为全球增长最快的主要经济体之一,其金融市场具有以下显著特征: 双交易所体系:国家证券交易所(NSE)和孟买证券交易所(BSE)高流动性品种:Nifty 50指数成分股、银行股等独特交易机制:T2…

2021-10-26 C++繁忙通信兵

缘由繁忙的通讯兵,可以解决一下吗-编程语言-CSDN问答 void 繁忙通信兵() {//缘由https://ask.csdn.net/questions/7544401?spm1005.2025.3001.5141int a 200, s1 8, s2 5, s3 45, p 0, n 0, c 0;std::cin >> n;while (a > n){a - s1 s2;if (a &l…

【Linux】进程控制:创建、终止、等待与替换全解析

文章目录 前言一、重谈进程创建二、进程终止2.1 正常终止的退出码机制2.2 异常终止的信号机制2.3 进程常见的退出方法 三、进程等待:避免僵尸进程的关键3.1 进程等待的必要性3.2 进程等待的两个系统调用接口3.2.1 wait()3.2.2 waitpid()区别 四、进程程序替换4.1 进…

基于Redis实现短信防轰炸的Java解决方案

基于Redis实现短信防轰炸的Java解决方案 前言 在当今互联网应用中,短信验证码已成为身份验证的重要手段。然而,这也带来了"短信轰炸"的安全风险 - 恶意用户利用程序自动化发送大量短信请求,导致用户被骚扰和企业短信成本激增。本…

【后端开发】Spring MVC-常见使用、Cookie、Session

文章目录 代码总结初始化--RestController、RequestMapping传递参数单参数多参数 传递对象后端参数重命名(后端参数映射)--RequestParam必传参数设置非必传参数 传递数组传递集合传递JSON数据JSON语法JSON格式转换JSON优点传递JSON对象 获取URL中参数--P…

青少年编程考试 CCF GESP Python七级认证真题 2025年3月

Python 七级 2025 年 03 月 题号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 答案 B C A B B A A B C A B B A B A 1 单选题(每题 2 分,共 30 分) 第 1 题 下列哪个选项是python中的关键字? A. function B. class C. method D. object…

Vue 框架组件间通信方式

组件间通信方式 不管是 vue2 还是 vue3,组件通信方式很重要,以下是常见的几种通信方式: props:可以实现父子组件、子父组件、甚至兄弟组件通信自定义事件:可以实现子父组件通信全局事件总线 $bus:可以实现…

SpringBoot学生成绩管理系统设计与实现

概述 幽络源本次分享的基于SpringBoot的学生成绩管理系统项目,采用主流的Java技术栈开发,实现了从学生信息管理到成绩统计分析的全流程数字化管理。 主要内容 管理员功能模块 ​​学生信息管理​​:维护学生基本信息档案,支持…

青少年编程与数学 02-016 Python数据结构与算法 01课题、算法

青少年编程与数学 02-016 Python数据结构与算法 01课题、算法 一、算法的定义二、算法的设计方法1. 分治法2. 动态规划法3. 贪心算法4. 回溯法5. 迭代法6. 递归法7. 枚举法8. 分支定界法 三、算法的描述方法1. **自然语言描述**2. **流程图描述**3. **伪代码描述**4. **程序设计…

Java 实现冒泡排序:[通俗易懂的排序算法系列之二]

引言 大家好!欢迎来到我的排序算法系列第二篇。今天,我们将学习另一种非常基础且广为人知的排序算法——冒泡排序 (Bubble Sort)。 冒泡排序的名字非常形象,它模拟了水中气泡上升的过程:较小(或较大)的元素会像气泡一样,通过不断交换,逐渐“浮”到数组的一端。 什么是…

struct结构体、union联合体和枚举

目录 一、结构体的声明和使用 1.1 结构体正常声明和创建 1.2 结构体特殊声明 1.3 结构体的自引用 二、结构体内存对齐 2.1 对齐规则 2.2 #pragma修改 三、结构体传参 四、结构体位段 4.1 位段内存分配 4.2 位段内存应用 五、结构体中的柔性数组概念 六、union联合…

大模型本地部署系列(2) Ollama部署DeepSeek-R1

成功运行截图 部署步骤 我们进入到ollama的官网: Ollama​ollama.com/​编辑 找到上方的Models ,然后点击 此时会跳转到模型列表页面: 点击 deepseek-r1 链接进去,此时我们会看到下拉框中有各个版本的大模型,越往后…

绘制动态甘特图(以流水车间调度为例)

import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np from matplotlib import cm# 中文字体配置(必须放在所有绘图语句之前) plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] Fa…

PyTorch实现线性回归的基础写法与封装API写法

目录 1. 基础写法 1.1导包 2.2加载读取数据 2.3原始数据可视化(画图显示) 2.4线性回归的(基础)分解写法 2.5定义训练过程 2.PyTorch实现 线性回归的封装写法(实际项目中的常用写法) 2.1创建线性回归模型 2.2定义损失函数 2.3定义优化器 2.4定义训练过程 1…

python 常用的6个爬虫第三方库

Python中有非常多用于网络数据采集的库,功能非常强大,有的用于抓取网页,有的用于解析网页,这里介绍6个最常用的库。 1. BeautifulSoup BeautifulSoup是最常用的Python网页解析库之一,可将 HTML 和 XML 文档解析为树形…

基于BP神经网络的杂草智能识别系统(杂草识别、Python项目)

基于BP神经网络的杂草智能识别系统 项目介绍 本项目是一个基于PyQt5和BP神经网络的杂草智能识别系统。系统通过图像处理和神经网络技术, 能够识别8种不同的杂草类别。用户可以通过上传图片,系统会自动识别图片中的杂草类别,并显示识别结果和…

Python3笔记之号称替代pip的uv包管理器

uv是什么? uv,这是一个由 Astral 团队开发的极快速的Python包和项目管理工具,用Rust语言编写。它集成了多种功能,旨在替代pip、pip-tools、pipx、poetry、pyenv、twine、virtualenv等多个工具,提供更高效、更全面的Py…

IT管理思路

甲方CIO和IT管理者-如何做好组织级IT能力提升_哔哩哔哩_bilibili

ChatGPT的GPT-4o创建图像Q版人物提示词实例展示

最近感觉GPT-4o发布的新功能真的强大,所以总结了一些提示词分享给大家,大家可以去试试,玩法多多,可以用GPT-4o生成图片,然后用可灵进行图生视频,就能去发布视频了!接下来和笔者一起来试试&#…

Transformer Decoder Block的几个优化方案

写在前面 在大型语言模型(LLM)的演进浪潮中,Transformer 架构凭借其强大的并行计算能力和对长距离依赖的出色捕捉,奠定了核心地位。然而,标准的 Transformer Decoder Block 遵循着一种相对固定的模式:先进行自注意力(Self-Attention)捕捉上下文信息,再通过前馈神经网…