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)()
相关推荐
汉字萌萌哒4 分钟前
2024CSP-J入门级C++真题详解
开发语言·c++
arbboter15 分钟前
【网络工具】NetProxy网络代理用户手册
开发语言·网络·c#·网络代理·网络异常·代理工具
汉字萌萌哒1 小时前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++
叠层归一研究院1 小时前
AGI 系统(十一):二阶网络 — 二阶递归 × 多主体 (元符号网络)
开发语言·人工智能·算法·php·agi
小雨笙笙2 小时前
C语言:变量三属性——存储类型
c语言·开发语言
果果燕2 小时前
C++ 学习笔记(二):类与对象—— 构造函数与析构函数
开发语言·c++
江畔柳前堤2 小时前
Function Calling 与 Tool Calling:从认知到工程的全景深度解析
开发语言·网络·人工智能·深度学习·算法·机器学习·php
2601_949950633 小时前
Java 面试准备,用练题簿把“背过八股”变成“真正会答”
java·开发语言·面试·刷题·小程序推荐
老洋葱Mr_Onion3 小时前
【C++】信息学奥赛CSP通关之路——CSP-J/S第一轮原创全真模拟试卷集(2026)卷四全卷解析
开发语言·c++
zander2583 小时前
LeetCode 739:每日温度——为什么单调栈要持续弹出
开发语言·python·算法