I have made a lua console on the love2d engine which is irrelevant. I am trying to upgrade the metatables to be able to effect more things (the pairs function, change the metatable on another table instead of the targeted one etc.) and one of the addons I am making is a __changeindex event for when you modify an existing index.
In order to do this I have to give the user a dummy table that holds no values and when they try to add something check if that is already defined in the real table, if it is then call __changeindex, if it is not then call __newindex. This works perfectly however this causes many other Lua table functions to stop working (for loops/getmetatable/setmetatable). I have made workarounds for most of those issues and they work fine but I cannot get the #t operator working, I would like to be able to say
t1={1,2,3}
t2=setmetatable({},{__getn=function(self) return #t1 end})
and then #t2 should really return #t1. Is there any way for me to do this?
my existing code for this can be found here
EDIT: this is my first post so I apologise if I have not followed the posting rules perfectly, I tried :) also if anyone has a way to make the fake and real tables garbage collect I would really appreciate it
There no __getn metamethod. Try __len instead. This works only on Lua 5.2
You cannot overload the # operator for tables in Lua 5.1
You could use userdata to create a proxy object:
t = newproxy(true)
getmetatable(t).__len = function()
return 5
end
print(#t) --> 5
Note however, that the newproxy function is undocumented.
Related
In a Roblox game I'm programming, I want to have a table of boolean values to iterate over ensuring that they're all false before making another one true, e.g.;
local bool1 = true
local bool2 = false
local bool3 = false
local bool4 = false
local tbl1 = {}
table.insert(tbl1,boolX) -- where "X" is the number above, did this in interest of shortening
for i,v in pairs(tbl1) do
if v then v = not v end
end
However, as stated in the penultimate paragraph of section 2.1 of the 5.3 manual (knowing, albeit, that Luau uses 5.1 as its base);
Tables, functions, threads, and (full) userdata values are objects: variables do not actually contain these values, only references to them. Assignment, parameter passing, and function returns always manipulate references to such values; these operations do not imply any kind of copy.
That in mind, that means that I'm not actually shoving bool1 through bool4 into the table, just their values; the table would look like {true, false, false, false}. This means that I can't simply write a loop to iterate through the table and invert any trues I find;
local bool1 = true
local tbl1 = {}
table.insert(tbl1,bool1)
tbl1[1] = false
print(bool1)
print(tbl[1])
--output:
-- true
-- false
I should point out that I very well could just shove all my variables into one giant if/else and call it a night, but that is a lot of variables to check, a lot of typing, and I can't think of any other more elgant and less tedious way other than finding a form of iteration over them all.
I want to be able to have an actual reference, in some form, to the actual variables so that I can modify them from within the table and make them iterable.
I've attempted to follow the examples given in the best answer to this question, with no successes. I would need to be able to, and cannot with these examples, substitute for any given variable at any given time, rather than just having one or two I want declated and thus returned as shown. I've attempted wrapping them in a function to provide my table and variable as arguments, but that doesn't seem to have any effect; it either outputs nothing, or nil.
The following answer after has one example that seems like it could work, but overall is pointless for what I'm trying to achieve; I don't want to re-declare or re-assign the variables I already have, I just want to return the specific value.
I've attempted using a key/value pair, making the key the potential variable name and making it equal the variable's value, but I've no way to make that key return a variable of the same name. I even attempted merging this method and the setmetatable method mentioned in the first set of examples to see if I couldn't substitute from there, to no avail.
I should point out that, while I'm not a complete newbie to Lua or Luau, I'm also not an expert in the field by any meaning of the word; I'll catch on quick, but where possible, explain like I'm 10.
The only way to iterate over local variables that are not referenced by table fields, is to use debug.getlocal in a loop.
Opinionated:
But this is a very bad approach to your problem.
You should refactor the code. If you need to update a list of variables have them in a list from the start. Don't be afraid of refactoring. Improving things usually pays off on the long term.
If your codebase is so bad that you are afraid of putting a few variables into a table you should really think over the design.
There is no way to do this in Roblox Luau.
Any potential way to do so in standard Lua is impossible to do in Luau due to how heavily sandboxed the latter is compared to the former.
Possible solutions that were recommended via comments include: making the variables needed available in _G as globals, then using them there; or using a pointer value in the table equivalent to the one you want, even though it won't technically change the value you want itself.
Another answer recommends the use of debug.getlocal() for standard Lua, but doesn't work in Luau; keep this in mind when attempting to use it, as you will get an attempt to call a nil value error.
The recommended way to do this is not to do it at all, and instead have your variables and/or values in your table from the start.
Not only does this provide ease-of-access in many cases, but it will allow you to iterate through them significantly easier than trying to shove them into tables and the like. Refactoring, if you need to do something similar to this, is highly recommended across the board.
I am creating a game in love2d (LuaJIT) and I am creating a debug window for changing values at runtime. I was able to do that, however, I also now want to be able to call functions. For example, I traverse a table and there is a function in this table called "hello" which is written like this:
self.hello = function(str, num)
print(string.format("%s: %d", str, num))
end
From the expression of type(object.hello) I only see function. If it had been a table, I could have traversed it and see the keys and values, but it is just a "function" and I have no idea how to properly call it, as I don't know what arguments does it take and how many. Is there a way to find this out at runtime in lua? Maybe this information is also stored in some table elsewhere?
it is just a "function" and I have no idea how to properly call it
Neither does Lua. As far as Lua is concerned, any Lua function can take any number of parameters and return any number of parameters. These parameters could be of any type, as could its return values.
Lua itself does not store this information. Or at least, not in any way you could retrieve without doing some decompiling of its byte-code. And since you're using LuaJIT, that "decompiling" might require decompiling assembly.
I am creating a caching system for complex shapes in Lua and I want it to be backwards compatible as a plug and play replacement for the default, non cached system, to increase performance. I've successfully rendered an object with 6.4 million points which gets turned into 3.1 million trapezoids to make a shape instead of using 6.4 million triangles, cache it and continue rendering without any performance hit beyond initial caching.
I want to set up a cached data table which uses the reference to the original table as the index. The problem is, if I use tostring, I end up with the entire table as a nicely formatted human-readable string which wouldn't be nice to use as a short index to reference the table.
I do not want to require the dev to assign an ID to the object because the default system doesn't do this, and it is an extra step which can be avoided by simply using the address which is unique to that object anyways..
I can not find a Lua implementation of lua_topointer(L, idx)... but maybe I'm missing something?
A few issues - my tostring no longer shows table: 0x12345678
I have rewritten a lot of meta-functions and __tostrings to output the data for debugging purposes. But, on Lua demo I can't find the exact function which replaces this behavior, and I didn't replace print in my latest version. So print is default, etc...
On Lua demo I have also tried getmetatable table, function m:__tostring( ) return 'blah' end
and print( { } ), print( tostring( { } ) )
The first prints the address. The second prints blah. So because print isn't using tostring, by default, what is it using? Is that accessible via Lua?
If all else fails, I'll probably have to get rid of my __tostring table metamethod and make a secondary function to output that particular data type which defaults the purpose of having a __tostring method for everything ( and the fact that print ignores it; one of the reasons I rewrote print in an old version... but I reverted to keep it default )
So, does anyone know a Lua function I can call, which is not tostring, which can get the address of a table in Lua? It must return the value so it can be used.
I'm sure many of you already know that the pairs function just returns next, t, and nil. What is the point of this? I've heard some say it's for readability but I think it just confuses people about the structure of a for loop.
So why does it exist?
In Lua 5.2, the __pairs and __ipairs metamethods were added to allow tables to have custom iterators. Not only that, but it's easier to read. There's also a __next metamethod as of Lua 5.2.
Reference
Hi and thanks in advance. I'm trying to see if there's a way to avoid learning C (which I don't know at all) to turn userdata into a Lua table.
I'm using an application which lets users write addons using Lua scripts. These addons can query the application's underlying data. However the query results are returned as userdata and I need them to be available back in the script.
I haven't been able to find anything in the applications documentation about working with returned datasets. The only description given is that the operation I'm running:
Executes the currently assigned query string and uses the results to construct either a DataSet object if multiple result sets are returned or a DataTable if one or no result sets are returned.
In my case I'll be getting multiple result sets, I'm referring to it as userdata because that's what I get when I call type() on the query result.
I've looked at the Lua documentation which seems like it could be useful but lacking any familiarity with C I have no idea what I'm looking at. The metatable tells me I have access to the __index, __newindex, __tostring, and __gc metamethods. Calling tostring gives me a seven-digit integer which is (I think) completely unrelated to my data. It's possible I'm not even getting the data I want back at all, but I can't figure a way to check that. Online resources either say this can't be done or provide solutions in C which are probably clever, clean, and awesome but I don't understand them.
So I'm looking for some more definitive guidance on whether I can/should do this, if there's a way to do this without C (or just by blindly copying someone else's code), or -- if I need to use C for this -- if we're talking about the 90 minute or the 7 hour Lynda Introduction to C course to get where I need to be?
(and apologies if I've inadvertently violated any community norms with this question...it's my first time posting)