I have 5000 data item definition configuration which we are expecting to be designed like,
-- Name of the device
VARIABLE Name {
type=Float,
length=20,
<<few more definition here>>
}
-- The device running elapsed time since its last boot
VARIABLE BootTime {
type=Integer,
<<few more definition here>>
}
I will be reading the value of "Name", "BootTime" from a device using diffent communication protocol where we use the above property defined.
I want the VARIABLE to also have properties to pre_processor and post_processor functions.
How to define the structure like this in Lua? If this strcuture is not possible, what is the closet structure possible in Lua
I want to overload operator for this Variable definitions so that I can do,
I can configure BootTime = 23456789 or
Do arithmetic like BootTime + 100 (milliseconds)
Or comparison like if BootTime > 23456789 then do something
If you can ditch the keyword VARIABLE then the code is Lua and you only need a little support code (some __index metamethod magic).
Integer="Integer"
setmetatable(_G,
{ __index = function(t,n)
return function (x) _G[n]=x.value end
end })
BootTime {
type=Integer,
value=10000
}
print(BootTime+2345)
If you want to keep the keyword VARIABLE then the syntax you gave is no longer plain Lua but if you can live with VARIABLE.BootTime or VARIABLE"BootTime" or VARIABLE[BootTime]then it is plain Lua and can be made to work with suitable metamethods.
Related
I have been playing with Lua for the past week and I ended up writing this peace of code. I find it really useful that you can dynamically create new functions that "inherit" other functions, so programmers must have a name for it. My questions are:
What is this called?
Is there a better way to do this? (cycle over a data structure and create add-on functions that "improve" existing functions)
D = {
name = {
value = nil,
offset = 0,
update = function (self)
self.value = "Berlin"
end,
},
}
--Dynamic function definition
for i in pairs(D) do
D[i].upAndWrite = function(self)
self:update()
print("upAndWrite was here")
end
end
print(D.name.value)
D.name:upAndWrite()
print(D.name.value)
Result:
nil
upAndWrite was here
Berlin
I don't think that what you're doing have special name for it, it's just on-the-fly function creation.
There are few notes regarding your code:
Proper for loop
for i in pairs(D) do
…
end
In programming, variable i is generally used for counter loops, like in
for i=1,100 do
…
end
Here, pairs returns an iterator function and the idiomatic way to use it is
for k,v in pairs(D) do
…
end
Here k is a key (like i in your code) and v is a value (use it instead of indexing table like D[k] or D[i] in your code when you need to access the corresponding value).
There's no need to create functions on the fly!
Another important thing is that you create new function on each loop iteration. While this feature is very powerful, you're not using it at all as you don't store anything using upvalues and only access data through arguments.
A better way to do it would be creating function once and assigning it to every field:
-- Define D here
do
local function upAndWrite(self)
self:update()
print("upAndWrite was here")
end
for k,v in pairs(D) do
v.upAndWrite = upAndWrite -- Use our function
end
end
-- Perform tests here
What does on-the-fly function creation allow?
As mentioned above, you can utilize this very powerful mechanism of closures in certain situations. Here's a simple example:
local t = {}
for i = 1, 100 do
-- Create function to print our value
t[i] = function() print(i) end
-- Create function to increment value by one
t[-i] = function() i=i+1 end
end
t[1]() -- Prints 1
t[20]() -- Prints 20
t[-20]() -- Increment upvalue by one
t[20]() -- Now it is 21!
This example demonstrates one possible usage of upvalues and the fact that many functions can share them. This can be useful in a variety of situations together with the fact that upvalues can't be changed by side code (without use of debug library) and can be trusted in general.
I hope my answer covers what you wanted to know.
Note: Also, this language is called Lua, not LUA.
As a whole it doesn't have a name, no. There's lots of concepts that play into this:
First Class Functions aka. functions that can be assigned to variables and passed around just like numbers or strings.
Anonymous Functions aka. functions that are created without giving it a name explicitly. All functions in Lua are technically anonymous, but often they are assigned into a variable right after creation.
Metaprogramming aka. writing programs that write programs. A loop that creates functions (or methods) on an arbitrary number of objects is very simple, but I'd count it as metaprogramming.
Lua Tables; this may seem obvious, but consider that not all languages have a feature like this. Javascript has objects which are similar, but Ruby for example has no comparable feature.
If you're gonna use pairs, you might as well make use of both variables.
for key, object in pairs(D) do
function object:upAndWrite(self)
self:update()
print("upAndWrite was here")
end
end
Though that would create many closures, which means more work for the garbage collector, more memory usage and slower execution speed.
for key, object in pairs(D) do
print(object.upAndWrite) -- All the functions are different
end
It's a good first stage, but after refactoring it a bit you could get this:
do
local method = function(self) -- Create only one closure
self:update()
print("upAndWrite was here")
end
for key, object in pairs(D) do
object.upAndWrite = method -- Use single closure many times
end
end
Now there's only one closure that's shared among all the tables.
for key, object in pairs(D) do
print(object.upAndWrite) -- All the functions are the same
end
This is more of a design philosophy question as I already know you shouldn't call a function with : (object-oriented syntactic sugar) if the function has been defined without the self keyword by using .. But the problem is that programmers using a library I have created tend to not read the documentation and run into the question of "how should I call your function?", so I end up always defining functions using the method below:
local tbl = {};
function tbl:Add(a, b)
return a + b;
end
I have installed Luacheck (in VS Code) and it often complains when I use this syntax and not use the self referential keyword. It says: [luacheck] unused argument "self". Is there any problem with this in terms of performance (or is there a way of disabling Luacheck in VS Code)?
I prefer writing functions in this style as opposed to the style below:
function tbl.Add(_, a, b)
return a + b;
end
It seems a pain to have to add a dummy variable at the start of the parameter list.
EDIT: Another problem is what if you had many tables that implement a function with the same name and want to iterate over them but some implementations do not use the self argument and others do? It would be very tedious and bad design to check what type of table it is to call the function correctly.
What is the preferred style? A bit confused in general about this warning. What are your thoughts? Thanks.
if you're not using the self argument you can just do
function tbl.Add(a, b)
return a + b;
end
no need to use a dummy variable.
You just need to be sure then that you also call it with a . and not a :
so
local someValue = tbl.Add(1, 3)
for example and not
local someValue = tbl:Add(1, 3)
I'm trying to figure out a way to get all functions in a Lua script. This script has been compiled into a function through loadfile. For example, I'd want to get every function defined in the script below.
function example1()
end
local function example2()
end
local library = {}
function library:example3()
end
(function()
-- Functions like this too.
end)
The names aren't important, I'm just looking for a way to get the actual functions so I can use them in debug.getinfo and get information like the lines they were defined in. I have LuaJIT, if that makes this any easier. Is something like this even possible? Thanks in advance.
I guess the file declares its functions as global, or it would be really easy to track what is returned.
If that's the case, you can cycle through all the global items with a generic for loop, and only take the functions from them:
allFuncs = {}
for key, item in pairs(_G) do
if type(item) == "function" then
allFuncs[#allFuncs + 1] = item
end
end
(_G is the table holding all the global variables)
Then you will have a list (allFuncs) holding all the functions declared, but be aware that it will also contain default functions like setmetatable or xpcall.
It's easy to modify the code to not make this happen, but only use this for testing / learning:
function allFuncs()
local funcsTab = {}
for key, item in pairs(_G) do
if type(item) == "function" then
funcsTab[#funcsTab + 1] = item
end
end
return funcsTab
end
defaultFuncs = allFuncs()
--then you load your file: other functions get declared
--we create another table containg the default + the new functions
myFuncs = allFuncs()
--then you subtract the first table from the second
for i = 1, #myFuncs do
for o = 1, #defaultFuncs do
if myFuncs[i] == defaultFuncs[o] then
table.remove(myFuncs, i)
end
end
end
This is if your file doesn't return anything and declares its functions as globals.
If the file declares them as local and then returns a table containing them, just use the first piece of code replacing _G with that returned table.
This is not likely to be possible without syntax or bytecode analysis as each function definition is an assignment (just has different forms in your examples). See the bytecode inspector and a related discussion here. For the syntax analysis you can use metalua or something like lua-loose-parser. Keep in mind that even those tools won't give you the entire list of functions as some functions may be defined dynamically using loadstring (or similar methods).
If you only have access to the result of loadfile, then you best bet is to use the bytecode analyzer.
This is possible using jit.attach in LuaJIT.
You can attach callbacks to a number of compiler events with
jit.attach. The callback can be called:
when a function has been compiled to bytecode ("bc");
when trace recording starts or stops ("trace");
as a trace is being recorded ("record");
or when a trace exits through a side exit ("texit").
http://wiki.luajit.org/JIT-Compiler-API#jit-attach
jit.attach(function(f)
local funcInfo = jit.util.funcinfo(f)
end, "bc")
What is the advantage of having this/self/me pointer mandatory explicit?
According to OOP theory a method is supposed to operate mainly (only?) on member variables and method's arguments. Following this, it should be easier to refer to member variables than to external (from the object's side of view) variables... Explicit this makes it more verbose thus harder to refer to member variables than to external ones. This seems counter intuitive to me.
In addition to member variables and method parameters you also have local variables. One of the most important things about the object is its internal state. Explicit member variable dereferencing makes it very clear where you are referencing that state and where you are modifying that state.
For instance, if you have code like:
someMethod(some, parameters) {
... a segment of code
foo = 42;
... another segment of code
}
when quickly browsing through it, you have to have a mental model of the variables defined in the preceding segment to know if it's just a temporary variable or does it mutate the objects state. Whereas this.foo = 42 makes it obvious that the objects state is mutated. And if explicit dereferencing is exclusively used, you can be sure that the variable is temporary in the opposite case.
Shorter, well factored methods make it a bit less important, but still, long term understandability trumps a little convenience while writing the code.
You need it to pass the pointer/reference to the current object elsewhere or to protect against self-assignment in an assignment operator.
What if the arguments to a method have the same name as the member variables? Then you can use this.x = x for example. Where this.x is the member variable and x is the method argument.
That's just one (trivial) example.
I generally use this (in C++) only when I am writing the assignment operator or the copy constructor as it helps in clearly identifying the variables. Other place where I can think of using it is if your function parameter variable names are same as your member variable names or I want to kill my object using delete this.
Eg would be where member names are same as those passed to method
public void SetScreenTemplate(long screenTemplateID, string screenTemplateName, bool isDefault)
{
this.screenTemplateID = screenTemplateID;
this.screenTemplateName = screenTemplateName;
this.isDefault = isDefault;
}
I'm going back to the basics here but in Lua, you can define a table like so:
myTable = {}
myTable [1] = 12
Printing the table reference itself brings back a pointer to it. To access its elements you need to specify an index (i.e. exactly like you would an array)
print(myTable ) --prints pointer
print(myTable[1]) --prints 12
Now functions are a different story. You can define and print a function like so:
myFunc = function() local x = 14 end --Defined function
print(myFunc) --Printed pointer to function
Is there a way to access the body of a defined function. I am trying to put together a small code visualizer and would like to 'seed' a given function with special functions/variables to allow a visualizer to 'hook' itself into the code, I would need to be able to redefine the function either from a variable or a string.
There is no way to get access to body source code of given function in plain Lua. Source code is thrown away after compilation to byte-code.
Note BTW that function may be defined in run-time with loadstring-like facility.
Partial solutions are possible — depending on what you actually want to achieve.
You may get source code position from the debug library — if debug library is enabled and debug symbols are not stripped from the bytecode. After that you may load actual source file and extract code from there.
You may decorate functions you're interested in manually with required metadata. Note that functions in Lua are valid table keys, so you may create a function-to-metadata table. You would want to make this table weak-keyed, so it would not prevent functions from being collected by GC.
If you would need a solution for analyzing Lua code, take a look at Metalua.
Check out Lua Introspective Facilities in the debugging library.
The main introspective function in the
debug library is the debug.getinfo
function. Its first parameter may be a
function or a stack level. When you
call debug.getinfo(foo) for some
function foo, you get a table with
some data about that function. The
table may have the following fields:
The field you would want is func I think.
Using the debug library is your only bet. Using that, you can get either the string (if the function is defined in a chunk that was loaded with 'loadstring') or the name of the file in which the function was defined; together with the line-numbers at which the function definition starts and ends. See the documentation.
Here at my current job we have patched Lua so that it even gives you the column numbers for the start and end of the function, so you can get the function source using that. The patch is not very difficult to reproduce, but I don't think I'll be allowed to post it here :-(
You could accomplish this by creating an environment for each function (see setfenv) and using global (versus local) variables. Variables created in the function would then appear in the environment table after the function is executed.
env = {}
myFunc = function() x = 14 end
setfenv(myFunc, env)
myFunc()
print(myFunc) -- prints pointer
print(env.x) -- prints 14
Alternatively, you could make use of the Debug Library:
> myFunc = function() local x = 14 ; debug.debug() end
> myFunc()
> lua_debug> _, x = debug.getlocal(3, 1)
> lua_debug> print(x) -- prints 14
It would probably be more useful to you to retrieve the local variables with a hook function instead of explicitly entering debug mode (i.e. adding the debug.debug() call)
There is also a Debug Interface in the Lua C API.