local Table = {}
local Metatable = {
__index = function(Table, Key)
return Key .. " Does Not Exist. Creating Place For It"
end,
newindex = function(Table, Key)
table.insert(Table, Key)
end
}
setmetatable(Table, Metatable)
print(Table.x)
for i, v in pairs(Table) do
print(i, v)
end
It is called __newindex not newindex.
Also you’re not pushing anything new into the table.
Also you should not use table.insert because that will throw a stack overflow. (Recursively fires itself basically). Instead use rawset(table, #table + 1, value)
Like for example when you want to make a read only table, you add this metamethod to proxy table’s metatable to prevent someone from inserting a new value or changing an existing one on the main table.
For what it’s worth, __newindex only fires for new indexes, not changed ones. People usually use a proxy with __newindex and __index that does not directly store any data to make a ‘true’ read-only table.
Here’s an example of using “proxy tables” to implement member access controls, e.g. private fields with getters and setters. This enables you to do strict encapsulation, forcing external code to interface with your modules exactly how you specify. You can do input validation e.g. when external code tries to set a member to a new value, or even wacky stuff like having side-effects to getters or whatever.
You could do this without proxy tables, but you’d have to write methods called something like “SetHealth” that outside programmers would have to remember and call correctly. With proxy tables it’s just “thing.Health = 50”. With the “old” way outside programmers could also mess up by e.g. overwriting methods in modules.
Copy/paste into a script or https://www.lua.org/cgi-bin/demo
--Normal module stuff
local MyModule = {
x = 10,
y = 5,
z = 8,
timesXAccessed = 0,
}
function MyModule:Test()
print("works with methods too!")
end
function MyModule:PrivateTest()
print("No way for outsiders to access this")
end
--Getters and setters stuff
local function defaultGetterFactory(key)
return function()
return MyModule[key]
end
end
local getters = {
["x"] = function()
MyModule.timesXAccessed = MyModule.timesXAccessed + 1
return MyModule.x * MyModule.timesXAccessed
end,
["y"] = function()
return MyModule.y % 2
end,
["z"] = defaultGetterFactory("z"),
["Test"] = defaultGetterFactory("Test")
}
local setters = {
["z"] = function(value)
MyModule.z = math.max(0, value)
end
}
--Just for convenience
function errorf(pattern, ...)
error(string.format(pattern, ...))
end
-- Proxy stuff
local myModuleProxy = setmetatable({}, {
__newindex = function(t, k, v)
if setters[k] then
return setters[k](v)
else
errorf("Tried to set %s of MyModule.", k)
end
end,
__index = function(t, k, v)
if getters[k] then
return getters[k]()
else
errorf("Tried to get %s of MyModule.", k)
end
end
})
--Return the proxy instead of the module itself
--return myModuleProxy
--Test stuff
--These are defined by the module
print(myModuleProxy.x)
print(myModuleProxy.x)
print(myModuleProxy.x)
print(myModuleProxy.y)
print(myModuleProxy.y)
myModuleProxy.z = 50
print(myModuleProxy.z)
myModuleProxy.z = -50
print(myModuleProxy.z)
print(myModuleProxy:Test())
--These will error
myModuleProxy.x = 2
myModuleProxy.y = 5
The kind of proxies talk about in this thread and “internet proxies” like mentioned in the thread you linked aren’t the same at all. They just happen to be called similar names. No, you can not use it to setup a proxy server.
In English, a “proxy” is something that represents something else. Both ideas are named after this.
A “proxy table” represent another table. By putting in a “middleman” between the “real” table and the programs that want to interact with it, we can control how this interaction happens and achieve a degree of encapsulation for that table. E.g. we might prevent a programmer from using a module in the wrong way, throwing an error if they try.
A “proxy server” represents another computer. If you’re browsing the web “normally”, your computer sends data over the internet to e.g. devforum.roblox.com, which sends back some other data. Your computer asks to see a specific thread, the devforum server sends some data back containing the text people posted in that thread. If you’re browsing through a proxy server, you don’t send data to devforum.roblox.com, and it doesn’t send data back to you. Instead, you send data to that proxy server, which then sends it to devforum.roblox.com, which sends some data back to the proxy server, which sends that back to you. Just like with the proxy tables, this allows you to control how your computer interfaces with devforum.roblox.com. For example, the proxy server might not let the website know that it’s representing another computer, or not let it know which other computer it represents. This might be desirable if you’re concerned about privacy. Read more here.
As for newproxy, that’s a built-in function available in Lua 5.1 and Roblox’s homemade version of Lua. You can use it for many of the same things as setmetatable, but it has some differences that may or may not be important to you. Unfortunately it’s not very well documented, at least not from what I can tell after a quick google. Read up on it, and let us know if you have specific questions.