lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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.
> >>>
> >>>
> >>
> >>
> >>
> >
> >
> >
>
>
>