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)()
相关推荐
leiming616 小时前
C++ 01 函数模板
开发语言·c++·算法
大道随心16 小时前
【QT】自动化设备控制界面搭建
开发语言·qt·自动化
摆烂z16 小时前
maven中打包不打全部包+多线程打包
java·开发语言·maven
bj_zhb16 小时前
Python 内置的 HTTP 服务
开发语言·python·http
贺今宵16 小时前
安装java环境,安装jdk,jre,配环境win11
java·开发语言
雾岛听蓝16 小时前
C++类和对象(三):核心特性与实战技巧
开发语言·c++
SmoothSailingT17 小时前
C#——Interface(接口)
开发语言·c#·接口
利刃大大17 小时前
【JavaSE】十九、JVM运行流程 && 类加载Class Loading
java·开发语言·jvm
Clarence Liu17 小时前
Go Context 深度解析:从源码到 RESTful 框架的最佳实践
开发语言·后端·golang