lua-users home
lua-l archive

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


It was thus said that the Great Andrea once stated:
> Why get/setmetatable() are necessary?
> 
> One could simply set a special key such as __metatable by writing something
> like
> 
> mt = {}
> t = {}
> t.__metatable = mt
> 
> Instead of writing
> 
> setmetatable(t,mt)
> 
> And similarly for getmetatable()
> 
> So what is the reason to keep these functions?

  It's mostly exposing the functionality from the C API to Lua.  In C,
lua_setmetatable() and lua_getmetatable() are required for supporting
userdata, which are not Lua tables.  A good example of this is LPEG [1],
used to parse text by defining composable units of code.  For a small
example:

	lpeg   = require "lpeg"
	number = lpeg.R"09"^1 / tonumber
	list   = lpeg.Ct((number * lpeg.P","^-1)^1)

	nums = list:match "1,20,300,4000"
	print(nums[1],nums[2],nums[3],nums[4])

'list' is a userdata, which Lua knows nothing about, other than what it can
do via the metatable.  

  Another reason is that by just assigning the metatable to a field
__metatable required extra work by the Lua VM to check the key on each
assignment for the "special" field __metatable.  This also makes it hard to
pretect the __metatable from being manipulated.  

The metatable can be protected by setting, strangely enough, the __metatable
field to a value.

	t = setmetatable({},{ __metatable = {} })
	setmetatable(t,mt)
	x = getmetatable(t)
	for n,v in pairs(x) do print(n,v) end
	setmetatable(t,mt)

  With the __metatable field set to a table (and it can be any value other
than nil), getmetatable() will return *that* value rather than the actual
metatable, and trying to reassign a metatable will result in an error.

  -spc

[1]	http://www.inf.puc-rio.br/~roberto/lpeg/
_______________________________________________
lua-l mailing list -- lua-l@lists.lua.org
To unsubscribe send an email to lua-l-leave@lists.lua.org