Table of reference to variables in Lua - lua

I'm trying to keep track of various variables in a big Lua code base, for logging and analytics purposes.
Ideally I want to create a register function that registers an existing global variable and keeps a reference to that variable (can be anything from numbers, booleans or other tables) in a table.
This table will then be used to loop on and output the values of the registered variables at certain points of the execution.
I won't have control over what type of variables are used, and cannot change how those variables are setup. So I don't have the option of changing those variables to tables and such.
What would be the best approach in Lua?

Related

Referencing Two Separate Variables by One Name/Call

I am new to Lua and am not sure if this is even possible.
Referencing two separate variables by one name/call,
i.e,
local pieces = game.Workspace.Part1 In Addition to game.Workspace.Part2
Both are specific objects, not values.
short answer:
No
What you want to do is not possible in Lua, or in any other programming language I know of. What you want to achieve however, can easily be done.
The most straight-forward solution would be to just check your condition for either of the two values. If you need to do this often, you could make a function that checks the condition on both values, and if it happens with many different values, you can even write a function that returns another closure that checks your condition for two upvalues.
If what you care about is not so much easily checking a condition for both values, but to store them together in a semantically meaningful way, you can just put both of them in a table like {first = game.Workspace.Part1, second = game.Workspace.Part1}, and apply your condition to its elements first and second instead of the object itself.

What is the difference between lua_getmetatable and luaL_getmetatable

Lua API has a function lua_getmetatable which will fetch the table with metafunctions if the value has one.
Lua auxiliary library (which is part of lua API) has another function luaL_getmetatable which is a macro that will fetch a value from LUA_REGISTRYINDEX.
But another function from this library luaL_getmetafield with similar name does a completely different thing - it will look for a method in the get_metatable's location.
Why is there two different locations?
When is each metatable used?
lua_getmetatable gets the metatable associated with the given object. This is a fundamental feature; if this function didn't exist, there would be no way to access the metatable for a given object.
luaL_getmetatable is part of a convention for giving types to userdata (C objects that can be accessed from Lua) or classes of tables. In this convention you add tables to the registry with luaL_newmetatable, and then use these tables to represent the metatables for different userdata/table types (when you need them you can read them from the registry and set them with luaL_setmetatable).
This is a convenience feature only; and you do not need to follow this convention if you don't want to. Everything will still work if you place the metadata tables somewhere that isn't in the registry and bind them to your userdata with lua_setmetatable. That said, if the luaL_*metatable functions didn't exist, where would you put the tables that you were using to represent the different userdata/table types; and how would you find them again when you needed them for a second time? You could definitely solve this problem in a different way, but why not use the pre-built convention if it works for you.

Erlang ets:insert_new for bag

In my code I want to take advantage of ETS's bag type that can store multiple values for single key. However, it would be very useful to know if insertion actually inserts a new value or not (i.e. if the inserted key with value was or was not present in the bag).
With type set of ETS I could use ets:insert_new, but semantics is different for bag (emphasis mine):
This function works exactly like insert/2, with the exception that instead of overwriting objects with the same key (in the case of set or ordered_set) or adding more objects with keys already existing in the table (in the case of bag and duplicate_bag), it simply returns false.
Is there a way to achieve such functionality with one call? I understand it can be achieved by a lookup followed by an optional insert, but I am afraid it might hurt performance of concurrent access.

What is a "tag" in Lua 4.0?

I was reading the Lua 4.0 manual and I came across this "tag" thing but I have no idea what it is referring to.
http://www.lua.org/manual/4.0/manual.html#3
That's the section where it mentions it but I still have no idea what the manual is talking about.
TL;DR: Tags are the precursor to modern-day meta-tables. Where now the event-handler-pairs are stored directly in the meta-table using normal table-manipulation, as it is a normal table, then we used those tags, normal though unique numbers, and special data-structures, which restricted the events we could set, and had a different interface.
One of the disadvantages of tags was they could not be garbage-collected as they were normal numbers, and thus their associated data could not either.
Quoting the important parts of section 3 "types and tags":
Besides a type, all values also have a tag.
Each of the types nil, number, and string has a different tag. All values of each of these types have the same pre-defined tag. As explained above, values of type function can have two different tags, depending on whether they are Lua functions or C functions. Finally, values of type userdata and table can have variable tags, assigned by the programmer (see Section 4.8). The tag function returns the tag of a given value. User tags are created with the function newtag. The settag function is used to change the tag of a table (see Section 6.1). The tag of userdata values can only be set from C (see Section 5.7). Tags are mainly used to select tag methods when some events occur. Tag methods are the main mechanism for extending the semantics of Lua (see Section 4.8).
So, think of tags as unique ids.
Every value has a tag, depending on its type:
All values of the types nil, number, string, function (C-flavor), function (Lua flavor) have a type-specific tag set on the C side.
All values of the types table and userdata have tags too, but those are set by the programmer for each value indepent from any other.
tag returns the tag, settag sets it for table and userdata, newtag creates a new one.
And looking at section 4.8 "tag methods", we understand that those unique ids are just used for comfortably associating all values of the same Lua type (or for tables and userdatas of the same semantic user-type) with special behavior:
Lua provides a powerful mechanism to extend its semantics, called tag methods. A tag method is a programmer-defined function that is called at specific key points during the execution of a Lua program, allowing the programmer to change the standard Lua behavior at these points. Each of these points is called an event.
The tag method called for any specific event is selected according to the tag of the values involved in the event (see Section 3). The function settagmethod changes the tag method associated with a given pair (tag, event). Its first parameter is the tag, the second parameter is the event name (a string; see below), and the third parameter is the new method (a function), or nil to restore the default behavior for the pair. The settagmethod function returns the previous tag method for that pair. A companion function gettagmethod receives a tag and an event name and returns the current method associated with the pair.
Which just boils down to settagmethod and gettagmethod being used to manage a mapping from tag+event to handler, and the runtime using that as an extension point.
As LHF mentions below, there's a wealth of additional detail and history in The evolution of Lua, for example how the tag-methods evolved from the previous extension-mechanism of "fallbacks", which did not support different behavior for separate groups of values, instead being global.

seeking a "weak Lua registry"

Is there a way for C to reference an object in Lua 5.2 in the same way that you would use the reference system except that these references are weak and may be garbage collected at any time? In other words, is there a registry of all current Lua objects that does not influence the objects' reference count?
You can do this by introducing one level of indirection - instead of storing the values directly in registry and forcing it to be weak, do this:
Create a table
Make it weak by setting a metatable {__mode = "v"}
Store this table in the registry using some known but unique key
Keep all objects you want to track in this table
Use this table stored in registry instead of the registry itself to look up all your objects
Note that there is no "track of all Lua objects" (like ObjectSpace in Ruby), unless you use some heavy persistence like Pluto. You can only access objects you store/track yourself.

Resources