Lua怎么实现不可变数组?

文章导读
Previous Quiz Next 在 Lua 中,array 通过 table 实现。table 默认是可变的。考虑以下情况,我们有一个包含四个方向的数组。
📋 目录
  1. 只读/不可变数组的完整示例
  2. 示例 - 使用 rawset
A A

Lua - 不可变数组



Previous
Quiz
Next

在 Lua 中,array 通过 table 实现。table 默认是可变的。考虑以下情况,我们有一个包含四个方向的数组。

main.lua

-- 方向数组
directions = { "UP", "DOWN", "LEFT", "RIGHT"}

-- 修改现有方向
directions[3] = "LEFTMOST"

-- 添加新方向
directions[5] = "RIGHTMOST"

-- 打印更新后的值
print(directions[3])
print(directions[5])

输出

运行上述程序时,我们将得到以下输出−

LEFTMOST
RIGHTMOST

这里可以看到数组是可变的。现在没有直接方法使数组不可变,但我们可以使用 metatables 在一定程度上实现这一点。

定义获取只读数组的函数

function readonly(table)
   return setmetatable({}, {
      -- 将 index 设置为提供的 table
      __index = table,
	  
	  -- 防止添加新 index
      __newindex = function(table, key, value)
         error("ReadOnly Array. Permission denied.")
      end,
	  
	  -- 不允许 setmetatable, getmetatable 方法
      __metatable = false
   });
end

获取只读 table

-- 方向的只读数组
directions = readonly({ "UP", "DOWN", "LEFT", "RIGHT"})

只读/不可变数组的完整示例

在以下示例中,让我们检查数组的正常功能,并检查是否允许使用 index 记法修改只读数组。

main.lua

function readonly(table)
   return setmetatable({}, {
      -- 将 index 设置为提供的 table
      __index = table,
	  
	  -- 防止添加新 index
      __newindex = function(table, key, value)
         error("ReadOnly Array. Permission denied.")
      end,
	  
	  -- 不允许 setmetatable, getmetatable 方法
      __metatable = false
   });
end

-- 方向的只读数组
directions = readonly({ "UP", "DOWN", "LEFT", "RIGHT"})

-- 修改现有方向
directions[3] = "LEFTMOST"

-- 添加新方向
directions[5] = "RIGHTMOST"

-- 打印更新后的值
print(directions[3])
print(directions[5])

输出

运行上述程序时,我们将得到以下输出−

lua: main.lua:8: ReadOnly Array. Permission denied.
stack traceback:
	[C]: in function 'error'
	main.lua:8: in metamethod 'newindex'
	main.lua:23: in main chunk
	[C]: in ?

示例 - 使用 rawset

但我们仍然可以使用 rawset() 方法修改上述数组,如下所示 −

main.lua

function readonly(table)
   return setmetatable({}, {
      -- 将 index 设置为提供的 table
      __index = table,
	  
	  -- 防止添加新 index
      __newindex = function(table, key, value)
         error("ReadOnly Array. Permission denied.")
      end,
	  
	  -- 不允许 setmetatable, getmetatable 方法
      __metatable = false
   });
end

-- 方向的只读数组
directions = readonly({ "UP", "DOWN", "LEFT", "RIGHT"})

-- 修改现有方向
rawset(directions,3,"LEFTMOST")

-- 打印更新后的值
print(directions[3])

输出

运行上述程序时,我们将得到以下输出−

LEFTMOST