Lua Virtualization |
|
|
This page holds some information and discussion that might be useful to those interested in using Lua as a language that is fully virtualizable. |
|
In the Lua language, values are only partly "virtualizable". Here, virtualizable means that any object with a metatable (table or userdata) can act as if it were a value of any other type, including the built-in types. |
|
Here, virtualizable means that any object with a metatable (table or userdata) can act as if it were a value of any other type, including the built-in types. Following is a summary of how close the latest release of Lua (5.0.2) is to supporting this: |
|
Following is a summary of how close Lua (5.1) is to being virtualizable: |
|
Equality a == b Limited* __eq Ordering a < b Limited* __lt, __le |
|
Equality a == b Limited[*] __eq Ordering a < b Limited[*] __lt, __le |
|
Negation not a No |
|
Boolean Logic not a, a and b No |
|
Get length string.len(a) No Other utility string.find, etc. No |
|
Get length string.len(a) No[!] Other utility string.find, etc. No[!] |
|
Iterating for x in pairs(a) No for x in ipairs(a) No Fix is trivial with small overhead |
|
Length #a Mostly __len (but requires userdata before 5.2) Iterating for x in pairs(a) No Fix is trivial [#] raw operations rawget(a,k) No array functions table.insert(a,b) No |
|
Invoking a(x, y) Yes __call + |
|
Invoking a(x, y) Yes __call [+] |
|
Resuming coroutine.resume(a) No |
|
Resuming coroutine.resume(a) No[!] File handles io.type(a), ... No[!] See also I/O library abstraction [@] |
|
type function type(a) No |
|
* Limited: Lua defines an equality or inequality among different types to always yield false. |
|
[*] Lua defines an equality or inequality among different types to always yield false. The __eq metamethod also always returns true for values that are raw equal, but this doesn't support the behavior of the value NaN=0/0, where typically NaN ~= NaN. [+] There are a couple of places in Lua where the __call metamethod is not checked. One of these is the __index metamethod itself (this affects FuncTables). [!] Native types can have metatables, allowing you to using : notation (eg. aString:find(aPattern)), which is virtualizable. Only some types like strings have the metatable defined by default, but it can be added via debug.setmetatable. |
|
+ There are a couple of places in Lua where the __call metamethod is not checked. One of these is the __index metamethod itself (this affects FuncTables). |
|
[#] See GeneralizedPairsAndIpairs for virtualizing pairs/ipairs/next. Also see LuaFiveTwo. [@] LuaList:2008-07/msg00345.html, LuaList:2005-05/msg00178.html |
|
I made a couple of changes to the chart, I hope whoever created this page doesn't mind. Also, I put code at GeneralizedPairsAndIpairs which "virtualizes" (if you like) pairs and ipairs; it relies on some 5.1 API calls but could be easily modified for 5.0.2. Some (but not all) of the holes are filled-in in Lua 5.1. In particular, each native type has a metatable, allowing you to write string functions in : notation (eg. aString:find(aPattern)), which I think deals with all of the package.method issues in the chart. (The math library is not introduced into the Number metatable as of 5.1work6, but it is trivial to do.)Note: In the case of a .. b where one of a and b is a number and the other one is an object with a __concat metamethod, the number will be converted to a string before the metamethod is called. Also, .. is right-associative, but a has priority if both a and b have __concat metamethods. So presented with a .. b .. c, where all three have metamethods, the sequence will be: ameta.__concat(a, bmeta.__concat(b, c)). Furthermore, in the case of a .. 34 .. 56 the result will be ameta.__concat(a, "3456"). Some of these might be surprising. |
Note: In the case of a .. b where one of a and b is a number and the other one is an object with a __concat metamethod, the number will be converted to a string before the metamethod is called. Also, .. is right-associative, but a has priority if both a and b have __concat metamethods. So presented with a .. b .. c, where all three have metamethods, the sequence will be: ameta.__concat(a, bmeta.__concat(b, c)). Furthermore, in the case of a .. 34 .. 56 the result will be ameta.__concat(a, "3456"). Some of these might be surprising. |
Following is a summary of how close Lua (5.1) is to being virtualizable:
Operation Example Works? Metamethods/comments --------- ------- ------ -------------------- Numbers Arithmetic a + b Yes __add, __sub, __mul, __div, __pow, __unm Equality a == b Limited[*] __eq Ordering a < b Limited[*] __lt, __le Booleans Truth value if a then No Would add overhead to the idiom 'if table[key] then' Boolean Logic not a, a and b No Strings Concatenation a .. b Yes __concat (see below) Get length string.len(a) No[!] Other utility string.find, etc. No[!] Tables Indexing a[b] Yes __index Write to index a[b] = c Yes __newindex Length #a Mostly __len (but requires userdata before 5.2) Iterating for x in pairs(a) No Fix is trivial [#] raw operations rawget(a,k) No array functions table.insert(a,b) No Functions Invoking a(x, y) Yes __call [+] Threads Resuming coroutine.resume(a) No[!] File handles io.type(a), ... No[!] See also I/O library abstraction [@] Misc String repr. tostring(a) Limited __tostring (not honored by C lua_tostring) type function type(a) No
[*] Lua defines an equality or inequality among different types to always yield false. The __eq metamethod also always returns true for values that are raw equal, but this doesn't support the behavior of the value NaN=0/0, where typically NaN ~= NaN.
[+] There are a couple of places in Lua where the __call metamethod is not checked. One of these is the __index metamethod itself (this affects FuncTables).
[!] Native types can have metatables, allowing you to using : notation (eg. aString:find(aPattern)), which is virtualizable. Only some types like strings have the metatable defined by default, but it can be added via debug.setmetatable.
[#] See GeneralizedPairsAndIpairs for virtualizing pairs/ipairs/next. Also see LuaFiveTwo.
[@] LuaList:2008-07/msg00345.html, LuaList:2005-05/msg00178.html
Advantages of virtualization:
Disadvantages:
RiciLake adds:
a .. b where one of a and b is a number and the other one is an object with a __concat metamethod, the number will be converted to a string before the metamethod is called. Also, .. is right-associative, but a has priority if both a and b have __concat metamethods. So presented with a .. b .. c, where all three have metamethods, the sequence will be: ameta.__concat(a, bmeta.__concat(b, c)). Furthermore, in the case of a .. 34 .. 56 the result will be ameta.__concat(a, "3456"). Some of these might be surprising.