Lua上值与闭包

在Lua编程中,闭包允许函数访问其外部作用域的变量。这些被访问的外部变量在Lua内部被称为"上值"(upvalue)。

什么是上值(Upvalue)?

上值指的是被内部函数访问的外部局部变量。

Lua 复制代码
function create_counter()
    local count = 0  -- 这是一个上值
    
    return function()
        count = count + 1  -- 访问上值
        return count
    end
end

local counter = create_counter()
print(counter())  -- 输出: 1
print(counter())  -- 输出: 2

在这个例子中,`count`变量就是上值,它被内部函数访问,即使外部函数`create_counter`已经返回。

上值的两种状态

当外部函数仍在执行时,上值处于开放状态。此时:

  • 上值仍然存在于栈上
  • UpVal结构只保存指向栈的指针
  • 多个闭包可以共享同一个上值

当外部函数返回后,如果仍有闭包引用该上值,则上值转为关闭状态:

  • 值从栈复制到UpVal结构内部
  • 不再依赖栈的存在
  • 可以独立存在

源码:UpVal结构

cpp 复制代码
typedef struct UpVal {
  TValue *v;        /* 指向实际值的位置 */
  lu_mem refcount;  /* 引用计数 */
  union {
    struct {        /* 开放状态:链表管理 */
      UpVal *next;
      int touched;
    } open;
    TValue value;   /* 关闭状态:值存储 */
  } u;
} UpVal;

状态从开放到关闭的转换过程

之所以外部函数返回了,仍能访问到变量,就是存在这样的过程,把上值的值复制到内部保存起来,然后指针从指向栈改成指向内部成员值。

cpp 复制代码
// 1. 将值从栈复制到UpVal内部
setobj(L, &uv->u.value, uv->v);

// 2. 更新指针指向内部存储
uv->v = &uv->u.value;

// 3. 设置垃圾回收屏障
luaC_upvalbarrier(L, uv);

实际应用

状态管理

Lua 复制代码
function create_state_machine(initial_state)
    local current_state = initial_state
    local states = {}
    
    return {
        get_state = function() return current_state end,
        set_state = function(new_state) 
            current_state = new_state 
        end,
        add_state = function(name, handler)
            states[name] = handler
        end
    }
end

缓存

Lua 复制代码
function create_cache()
    local cache = {}
    local max_size = 100
    
    return {
        get = function(key) return cache[key] end,
        set = function(key, value) 
            if #cache >= max_size then
                -- 简单的LRU实现
                local oldest = next(cache)
                cache[oldest] = nil
            end
            cache[key] = value 
        end,
        clear = function() cache = {} end
    }
end

单例

Lua 复制代码
local singleton = (function()
    local instance = nil
    return function()
        if not instance then
            instance = create_instance()
        end
        return instance
    end
end)()
相关推荐
草履虫建模9 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
naruto_lnq11 小时前
分布式系统安全通信
开发语言·c++·算法
学嵌入式的小杨同学12 小时前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
Re.不晚12 小时前
Java入门17——异常
java·开发语言
精彩极了吧12 小时前
C语言基本语法-自定义类型:结构体&联合体&枚举
c语言·开发语言·枚举·结构体·内存对齐·位段·联合
南极星100513 小时前
蓝桥杯JAVA--启蒙之路(十)class版本 模块
java·开发语言
baidu_2474386114 小时前
Android ViewModel定时任务
android·开发语言·javascript
Dev7z14 小时前
基于 MATLAB 的铣削切削力建模与仿真
开发语言·matlab
不能隔夜的咖喱14 小时前
牛客网刷题(2)
java·开发语言·算法
小天源14 小时前
Error 1053 Error 1067 服务“启动后立即停止” Java / Python 程序无法后台运行 windows nssm注册器下载与报错处理
开发语言·windows·python·nssm·error 1053·error 1067