lua-users home
lua-l archive

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


> The example below introduced me to the newproxy() method. Unless I am 
> mistaken, in the example below, the use of newproxy() is crucial because 
> otherwise the type of the returned "u" variable will be "table", and 
> setting __len on the metatable of a table does not change the behavior 
> of the # operator.

Right.

> However, according to old newsgroup postings, newproxy() is an 
> unsupported method. Is there another way to create a userdata object 
> without using C code?

No, and newproxy is undocumented and unsupported. The motivation is given by
Roberto:

"This is a very experimental feature. We wanted a simple and secure way
of creating userdata in Lua. It has several uses, such as to monitor
garbage collection, as a light "unique" object, and for testing ;-).
But we cannot allow Lua to change the metatable of those userdata;
otherwise, Lua could break other libraries (e.g. give one of these
userdata as a file to be closed). To allow each userdata to have its own
new metatable or to share the metatable of another such userdata seems
flexible and secure."
http://lua-users.org/lists/lua-l/2002-09/msg00165.html

Rici Lake also offers some motivation and a reason for the function name:

"But the basic idea is simple enough: Sometimes all you need is a metatable;
creating a whole empty table to attach the metatable to is a bit wasteful.
Creating a zero-length userdata is cheaper, and you can attach a metatable
to it, but the standard interface doesn't allow Lua programs to either
create userdata or manipulate userdata metatables.

Solution: write a little C function which creates a zero-length full
userdata with a specific metatable. The function is, I believe, called
newproxy."
http://lua-users.org/lists/lua-l/2003-01/msg00205.html

Besides being cheaper, using userdata as proxies has the advantage over tables
of allowing __len metamethods, as you have already noticed. As other examples,
userdatum proxies can be used in http://www.lua.org/pil/13.4.4.html and
http://www.lua.org/pil/13.4.5.html instead of empty tables. For the latter:

function readonly(t)
  local u = newproxy(true)
  local mt = getmetatable(u)
  mt.__index = t
  mt.__newindex = function()
    error("attempt to update a read-only table", 2)
  end
  -- can't get this with table proxies:
  mt.__len = function() return #t end
  return u
end

Cheers,
Luis.

-- 
A mathematician is a device for turning coffee into theorems.
        -- P. Erdos 

-- 
Luis Carvalho
Applied Math PhD Student - Brown University
PGP Key: E820854A <carvalho@dam.brown.edu>