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)()
相关推荐
Web极客码26 分钟前
Python Ollama 本地 Agent 入门与订单查询实践
开发语言·jvm·python
kimnoic1 小时前
PHP 8.2的DNF类型怎么用才规范
开发语言·php
_Evan_Yao1 小时前
前后端联调怎么排查问题?从 Network 到后端日志,一步步定位错误
开发语言·后端·团队开发·需求分析
hudd6681 小时前
JavaEE 初阶 - 多线程(进阶)
java·开发语言·java-ee
小白快快跑哦2 小时前
python-字符串全解(六):正则表达式-前后相断言
开发语言·python·正则表达式·前后相断言
kimnoic2 小时前
Python数据分析中正则表达式匹配字符串与常用函数示例详解
开发语言·python
中屹指纹浏览器svip2 小时前
打开账号环境网页报错,常见原因有哪些?
服务器·开发语言·php·中屹指纹浏览器
朝朝辞暮i2 小时前
第 01 讲:Python 变量、对象、数据类型与内存引用
开发语言·python
外收内放2 小时前
Python基础语法练习题(69)
开发语言·python
lojox2 小时前
深入理解 C++ STL:vector 底层实现、迭代器失效与 list 特性
开发语言·c++