Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ Lua ➜ Metafunction __newindex calling itself

Metafunction __newindex calling itself

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by tobiassjosten   Sweden  (79 posts)  Bio
Date Sat 11 Nov 2006 06:09 PM (UTC)
Message
I want to create a function to use to initialize variable tables that will serialize themselves whenever something is changes within them. The only way I could think of doing this is with the metafunction __newindex. But since it seems to call itself I am getting a stack overflow error and it halts. Anyone know how do go about doing this?

require "serialize"

function VarInit(name)
	-- Declare and load the table
	_G[name] = {}
	if GetVariable(name) then loadstring(GetVariable(name))() end
	-- Set the metatable to save itself
	setmetatable(_G[name], {
		__index = function(t, k)
			return t['_' .. k]
		end,
		__newindex = function(t, k, v)
			_G[name]['_' .. k] = v
			SetVariable(name, serialize.save(name))
		end 
	})
end

Simplicity is Divine | http://nogfx.org/
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #1 on Sat 11 Nov 2006 06:47 PM (UTC)
Message
The problem is that you create an infinite number of new variables. Let's say you add the variable "foobar". The way your newindex works, it'll create _foobar. But that's a new index, so it creates __foobar... and ___foobar... and so forth.

What you probably want to do is make sure that the first character isn't an underscore before renaming it as you set the value.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by tobiassjosten   Sweden  (79 posts)  Bio
Date Reply #2 on Sat 11 Nov 2006 07:09 PM (UTC)
Message
That's how I tried doing it before, but since I wouldn't work I tried this approach, renaming them.

Simplicity is Divine | http://nogfx.org/
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #3 on Sat 11 Nov 2006 08:25 PM (UTC)
Message
Would you mind pasting the code you had before?

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by Nick Gammon   Australia  (23,140 posts)  Bio   Forum Administrator
Date Reply #4 on Sun 12 Nov 2006 04:43 AM (UTC)
Message
A variation on the technique described in http://www.gammon.com.au/forum/?id=4904 might work for you, as it maintains an empty "proxy" table, and access to the real data are view __newindex.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by tobiassjosten   Sweden  (79 posts)  Bio
Date Reply #5 on Sun 12 Nov 2006 08:37 PM (UTC)
Message
Before I had something like ..
require "serialize"

function VarInit(name)
	-- Declare and load the table
	_G[name] = {}
	if GetVariable(name) then loadstring(GetVariable(name))() end
	-- Set the metatable to save itself
	setmetatable(_G[name], {
		__newindex = function(t, k, v)
			SetVariable(name, serialize.save(name))
			_G[name][k] = v
		end 
	})
end


I've resorted to static names for my variables for now, but I'd still like a solution for this if anyone care to point me in a direction.

Using the proxy table to MUSHclient variables wouldn't work for me, since I'd need the variable to exist as a table (for iteration purposes). I could, ofcourse, track the initialized tables and serialize them when I finish my session. But I wanted to avoid doing that. Looks like a dead end to me. :/

Simplicity is Divine | http://nogfx.org/
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #6 on Sun 12 Nov 2006 09:09 PM (UTC)
Message
After reading through the Lua documentation, it appears that you need to use rawset to directly set the table value, bypassing __newindex. If you don't, Lua has no way to realize that you set the field from inside __newindex and will simply call it again.

So you'd do something like this:

	setmetatable(_G[name], {
		__newindex = function(t, k, v)
			SetVariable(name, serialize.save(name))
			rawset(t,k,v)
		end 
	})


(You might want to note that the 't' parameter is the current table. In your old code, even without the stack overflow, it was not a bug but a problem to explicitly refer to the table by name. With the new code, you can create the metatable only once and share it, thus saving some memory, instead of creating one copy per variable.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by tobiassjosten   Sweden  (79 posts)  Bio
Date Reply #7 on Mon 13 Nov 2006 10:43 PM (UTC)
Message
Never heard of the rawset function before. I'll try this out asap, thanks alot for the help!

Simplicity is Divine | http://nogfx.org/
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


22,487 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.