Can someone help me with __newindex?

So before I start yes I have looked at other threads about this etc but I still don’t get it.

I was wondering if someone could explain it in laymens terms and give me an example?

local Table = {}
local Metatable = {
	newindex = function(Table, Key)
		table.insert(Table, Key)
	end
}
setmetatable(Table, Metatable)

Am I using it correctly please give example.

2 Likes

Hi, what do you want to know about newindex?
This is not really well explained.
Yes’ that’s right.

you can also do:

local t = setmetatable({},{
__newindex = function(self,i,v)
rawset(self,i,v) -- doesn't fires __new index, otherwise stack overflow
end;
})
t.hi = true -- new index fires!
5 Likes

So will it fire and create a new thingy in the table if something i enter is not in the table?

2 Likes

And that piece of code did not work because

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

The table is stil emptyy

3 Likes

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)

2 Likes

hmm, when a new index is added it will fire.

1 Like

Can I get an example of when I would actually ever need to use newindex?

1 Like

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.

1 Like

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.

4 Likes

Can you please tell me what a proxy is and how and when do I use it?

1 Like

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

1 Like

Ok but what is newproxy for? And can I use this for this thread:Alternatives to HttpGet?

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.

1 Like