[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Checking if a table has changed
- From: "Leandro Candido" <enclle@...>
- Date: Fri, 12 Dec 2003 09:43:13 -0200
Hello Florian,
The answer is no, in first place, but you can use the metatable from
parent to break assignment to a child. In the newindex, you check if the var
is eligible for "readonly", and then you do nothing. If you don't want to
change tables, you do:
function meta.__newindex...
--...--
if type(rawget(self,"____X")[name]) == "table" then
return
end
--...--
end
But you need then to change from _G (global table) onward.
The God's Peace,
Leandro.
----- Original Message -----
From: "Florian Berger" <fberger@cs.joensuu.fi>
To: "Lua list" <lua@bazar2.conectiva.com.br>
Sent: Friday, December 12, 2003 9:02 AM
Subject: Re: Checking if a table has changed
>
> Hi.
>
> Thanks for the example! The example works perfectly. It took quite a
> while to figure out what is happening. I'm still having problems with
> metatables because I haven't used them very much.
>
> However I have an additional question. If I create a table that checks
> if it's contents are changed can I prevent the table to be set to other
> type (for example normal table, number)? So basically can I prevent an
> assignment to variable referencing to the table?
>
> Floru
>
>
>
> Leandro Candido wrote:
>
> > Hello All,
> >
> > IF and IF you want, Florian, you can use a function (initializer) to
> > create each table, too, it's easy to use:
> >
> > -- begin code
> >
> > function t( thetable )
> > local meta = {}; -- or create a global one.
> > function meta.__newindex( self, name, value )
> > -- do what you want (track the value, etc...)
> > -- ... --
> > print(self, name, value); -- comment for normal use.
> > rawget(self,"_______X")[name] = value; -- to allow meta call of
> > __newindex for X, if it has a metatab, see example in TWICE part below
> > end
> > function meta.__index( self, name )
> > -- do what you want here...
> > -- ... --
> > print(self,name);
> > return rawget(self,"_______X")[name]; -- to allow meta call of
__index
> > for X.
> > end
> > local tab = { _______X = thetable }
> > setmetatable( tab, meta);
> > return tab;
> > end
> >
> > mytable = t{ xyz = "123", lua_version = _VERSION }
> > another = t(mytable);
> > print(mytable.xyz);
> > print(mytable.lua_version);
> > print(mytable.nilfield);
> > print("\nNow the metamethods will be called twice (THIS IS TO BE
CALLED
> > TWICE):");
> > print(another.xyz);
> > print(another.lua_version);
> > print(another.nilfield);
> > print("\nNow, this will break our schema, of course:");
> > mytab = t{}
> > setmetatable(mytab,{});
> > print(mytab.nilfield);
> >
> > -- end code
> >
> > You can "seach and replace" all "{" with "t{" in your .lua files, and
you
> > will have what you want, but this can't be made automagically, as Virgil
(or
> > others) stated.
> >
> > The God's Peace,
> >
> >
> > Leandro.
> >
> >
> > ----- Original Message -----
> > From: "Virgil Smith" <virgil@nomadics.com>
> > To: "'Lua list'" <lua@bazar2.conectiva.com.br>
> > Sent: Thursday, December 11, 2003 2:59 PM
> > Subject: RE: Checking if a table has changed
> >
> >
> >
> >>I suggest you check the wiki and the list archives for Lazy Copy or Deep
> >>Copy (and/or RLake as I think he submitted the one I'm thinking of at
the
> >>moment).
> >>
> >>You can copy any table placed into your hierarchy (using a proxy table
at
> >>each level). This may seem inefficient, but I can't think of any other
> >>language in which you wouldn't have the same basic copy problem (though
I
> >>don't doubt others have). Basically, this relates to a question of
> >>ownership of an "object" and/or to attributes of the "object's" type (in
> >>this case a "modified" flag). You could restrict tables added to your
> >>hierarchy to be of a given "type" that supports a "modified" flag (and a
> >>parent pointer for passing modification notices up the hierarchy if you
so
> >>choose). The "type" of a table in Lua is related to its metatable.
> >>
> >>An aspect of the copy approach is that you cannot be sure that "other"
> >>references to the original table did not exist at the time that the
table
> >
> > in
> >
> >>question was inserted into your hierarchy. However, one approach to
this
> >>would be to "hijack" the original table as the proxy table. In other
> >
> > words
> >
> >>rather than copying the contents of a table that is being "inserted"
into
> >>your hierarchy, you could <move> the contents into another table. This
> >>would result in any "stray" references to the inserted table going
through
> >>one of your proxy tables and thus you can maintain your "modified" flag.
> >>One problem with this approach is that you must not only "hijack" the
base
> >>table, but also its metatable if it already has one. However, a Lua
table
> >>with a metatable is essentially a user defined type, object, or "class
> >>instance", and "seeing through" an unknown type to determine if it has
> >
> > been
> >
> >>modified etc. is not a simple problem in any language. Naturally,
> >>userdata's are just as much of an "unknown type" as tables with
> >
> > metatables,
> >
> >>and threads and functions bring up their own issues (though I'm not at
all
> >>sure about the "issues" with functions in this context).
> >>
> >>Anyhoo, just my suggestions, perhaps you'll even find them useful. :-)
> >>Also, if my use of the term "hierarchy" seems strange, try rereading the
> >>message using "tree" in its place.
> >>
> >>
> >>
> >>-----Original Message-----
> >>From: lua-bounces@bazar2.conectiva.com.br
> >>[mailto:lua-bounces@bazar2.conectiva.com.br]On Behalf Of Florian Berger
> >>Sent: Thursday, December 11, 2003 8:25 AM
> >>To: Lua list
> >>Subject: Re: Checking if a table has changed
> >>
> >>
> >>
> >>Thanks for the tip! I found code from lua-l archive (see below, I
> >>modified it a little bit). The problem is that as you can see that it
> >>does not work for nested tables. I could traverse recursively the
> >>subtables through and call proxy for each table but I cannot do this
> >>because of performance reasons. This cannot be automated somehow?
> >>
> >>Floru
> >>
> >>
> >>Source: http://lua-users.org/lists/lua-l/2003-07/msg00173.html
> >>
> >>do
> >> local signature = {}
> >>
> >> -- set a proxy on table
> >> function proxy(table)
> >> local meta =
> >> {
> >> __index = table,
> >>
> >> __newindex = function(_, index, value)
> >> print('Modified!')
> >> table[index] = value
> >> end,
> >>
> >> __signature = signature,
> >> }
> >>
> >> return setmetatable({}, meta)
> >> end
> >>
> >> local n = next
> >>
> >> -- next replacement to support pairs and "old style" for loops
> >> function next(table, index)
> >> local m = getmetatable(table)
> >> return n(m and m.__signature == signature and m.__index or table,
> >>index)
> >> end
> >>end
> >>
> >>local x = proxy( {{a = 1}, a = 1, b = 2} )
> >>
> >>for k, v in pairs(x) do
> >> print(k, v)
> >>end
> >>
> >>x[1].a = 5
> >>x.a = 2
> >>
> >>
> >>Result:
> >>1 table: 00379EB8
> >>a 1
> >>b 2
> >>Modified!
> >>
> >>
> >>
> >>
> >>Jamie Webb wrote:
> >>
> >>
> >>>On Thursday 11 December 2003 08:22, Florian Berger wrote:
> >>>
> >>>
> >>>>Hi.
> >>>>
> >>>>Is there a simple and efficient way to check if a table has changed?
By
> >>>>using metatables I'm able to catch some modifications but not all of
> >
> > them.
> >
> >>>
> >>>You could use a proxy table with a __newindex which makes modifications
> >
> > to
> >
> >>the
> >>
> >>>actual table and sets a 'modified' flag. Since the proxy table stays
> >>
> >>empty,
> >>
> >>>__newindex is always called.
> >>>
> >>> -- Jamie Webb
> >>>
> >>>There are only 10 types of people in this world:
> >>>those who understand binary, and those who don't.
> >>>
> >>>
> >>
> >>
> >>
> >
> >
> >
>
>
>