lua-users home
lua-l archive

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


Luiz Henrique de Figueiredo wrote:
> 
> >As for the __get and __set issue, proxy tables can
> >indeed be used, however, it would be nice if there was
> >an example in the official distribution.
> 
> See readonly.lua, trace-globals.lua, and undefined.lua in test/ .
> They use limited proxies (not totally empty tables), though.
> 

As those weren't to my liking, I wrote my own example
which follows below, which allows the metamethods
__get and __set to be used.  The idea is that you use 
the function makeproxy() directly after setting the 
metatable and use that proxy as a replacement for the 
real table. I haven't tested the other methods like 
__add, __sub, etc but it should also work for those metamethods.
Comments and improvements are welcome. I
would especially appreciate Jimmyp_gr's comments,
as he requested such functionality.

                                                                                                    
__proxy__index    = function
(t,i)                                                                  
local meta = getmetatable
(t)                                                                       
   if 
meta.__get                                                                                   
   then return
meta.__get(meta.target,i)                                                            
   else return meta.target[i];
end                                                                  
end                                                                                                 
                                                                                                    
__proxy__newindex    = function
(t,i,v)                                                             
local meta = getmetatable
(t)                                                                       
   if
meta.__set                                                                                    
   then
meta.__set(meta.target,i,v)                                                                 
   else meta.target[i] =
v                                                                          
  
end                                                                                              
end                                                                                                 

                                                                                  
function
makeproxy(tab)                                                                             
local proxy,
meta                                                                                   
meta =
getmetatable(tab)                                                                            
proxy = {  }; -- always
empty                                                                       
proxymeta = {
}                                                                                     
if
meta                                                                                             
  then for k, v in meta do 
rawset(proxymeta,k,v)                                                   
 
end                                                                                               
end                                                                                                 
-- copy the metatable, to get the
operators.                                                        
proxymeta.__index    =
__proxy__index                                                               
proxymeta.__newindex =
__proxy__newindex                                                            
-- override these
two.                                                                              
proxymeta.target =
tab;                                                                             
-- so we know whom we are
proxying!                                                                 
setmetatable(proxy,
proxymeta);                                                                     
return proxy;           
end                                                                                                 
                                                                                                    
-- example metatable, with the much desired __get and __set
methods.                                                                                                    
                                                                                                    
tabmeta =
{                                                                                         
__get = function(t,i) print "__get called!" return rawget(t, i)
end,                                
__set = function(t,i,v) print "__set called!" rawset(t, i,v)
end,                                   
__call = function() print "__call called!"
end,                                                     
__unm = function() print "__unm called!"
end                                                        
}                                                                                                   
                                                                                                    
mytab =
{                                                                                           
   first = "first
string"                                                                           
}                                                                                                   
                                                                                                    
setmetatable(mytab,tabmeta)                                                                         
mytab =
makeproxy(mytab)                                                                            
-- this is how "makeproxy" should be called.

-- some tests  
-- __get and __set from metatable should be
called.                                                                                                  

print(mytab.first)                                                                                  
mytab.first = "First string
again!"                                                                 
print(mytab.first) 
print(mytab.second)                                                                                 
mytab.second = "Second
line"                                                                        
print(mytab.second)                                                                                 
mytab.second = "Second line
again!"                                                                 
print(mytab.second)                                                                                 
mytab();                                                                                            
fake = -mytab;          



-- 
"No one knows true heroes, for they speak not of their greatness." -- 
Daniel Remar.
Björn De Meyer 
bjorn.demeyer@pandora.be