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
Related
I basically don't look for an answer on how to do something but I found how to do it, yet want more information. Hope this kind of question is OK here.
Since I just discovered this the code of a game I'm modding I don't have any idea what should I google for.
In Lua, I can have for example:
Account = {balance = 0}
function Account.withdraw (v)
self.balance = self.balance - v
end
I can have (in another lua file)
function Account.withdrawBetter (v)
if self.balance > v then
self.balance = self.balance - v
end
end
....
--somewhere in some function, with an Account instance:
a1.withdraw = a1.withdrawBetter
`
What's the name for this "technique" so I can find some more information about it (possible pitfalls, performance considerations vs. override/overwrite, etc)? note I'm only changing withdraw for the particular instance (a1), not for every Account instance.
Bonus question: Any other oo programming languages with such facility?
Thanks
OO in Lua
First of all, it should be pointed out that Lua does not implement Object Oriented Programming; it has no concept of objects, classes, inheritance, etc.
If you want OOP in Lua, you have to implement it yourself. Usually this is done by creating a table that acts as a "class", storing the "instance methods", which are really just functions that accept the instance as its first argument.
Inheritance is then achieved by having the "constructor" (also just a function) create a new table and set its metatable to one with an __index field pointing to the class table. When indexing the "instance" with a key it doesn't have, it will then search for that key in the class instead.
In other words, an "instance" table may have no functions at all, but indexing it with, for example, "withdraw" will just try indexing the class instead.
Now, if we take a single "instance" table and add a withdraw field to it, Lua will see that it has that field and not bother looking it up in the class. You could say that this value shadows the one in the class table.
What's the name for this "technique"
It doesn't really have one, but you should definitely look into metatables.
In languages that do support this sort of thing, like in Ruby (see below) this is often done with singleton classes, meaning that they only have a single instance.
Performance considerations
Indexing tables, including metatables takes some time. If Lua finds a method in the instance table, then that's a single table lookup; if it doesn't, it then needs to first get the metatable and index that instead, and if that doesn't have it either and has its own metatable, the chain goes on like that.
So, in other words, this is actually faster. It does use up some more space, but not really that much (technically it could be quite a lot, but you really shouldn't worry about that. Nonetheless, here's where you can read up on that, if you want to).
Any other oo programming languages with such facility?
Yes, lots of 'em. Ruby is a good example, where you can do something like
array1 = [1, 2, 3]
array2 = [4, 5, 6]
def array1.foo
puts 'bar'
end
array1.foo # prints 'bar'
array2.foo # raises `NoMethodError`
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")
So I'm just starting to learn Eiffel. One of the first exercises in the book I'm using says to make a function that does base^exp without using ^. I've copied my code below.
class
APPLICATION
inherit
ARGUMENTS
create
make
feature {NONE} -- Initialization
make
-- Run application.
do
create power(2;3)
printf("2 to the power of 3 is " + answer)
end
power(base : REAL; exp : INTEGER) : REAL
-- computers base raised to the bower of exp without using ^
local
remain : INTEGER
do
remain := exp
if remain = 0 then
result := 1
else
from
until
remain = 0
loop
result := result * result
remain := remain -1
end
end
end
end
How do I use this? Do I need it on the same level as feature{NONE}'s make? I know how I'm calling it is wrong, and I can't find anything in the chapter I just read, or online on how to pass parameters into it or how to use it's results.
There are several issues with the original code:
create is used to create an object, but you are not going to create anything, but to get a result of a computation of the function power by calling it. Therefore the keyword create is not needed.
You are using an entity answer to report the result of evaluation on a screen. However it is not declared anywhere. I believe the proper place would be a local variable declaration section.
The entity answer is not initialized to the result of the function power. This is usually done by an assignment instruction.
Feature arguments are separated by a comma, not by a semicolon.
From the original code it's unclear what is the type of the variable answer. Assuming it matches the type of the function power, before adding it to a string, it needs to be converted to a string. This is done by calling the feature out.
The standard feature for printing a string to a console is print, not printf.
Combining the critical points above, we get
make
-- Run application.
local
answer: REAL
do
answer := power(2, 3)
print ("2 to the power of 3 is " + answer.out)
end
After that the code can be compiled. Now less critical points:
It is a good style to put features to a dedicated feature clauses, so I would add a line like feature -- Basic operations before the feature power.
The implementation of the feature power has at least two problems. I'm not going to detail them here, but would give two hints instead:
by default numeric Result is initialized to 0, this needs to be taken into account for operations that use it without first assigning any other value
even though an argument base is passed to the function power it remains unused in the original version of the code
I have an object that I create using the following function
local function newObject(functionVariable)
...
functionVariable = functionVariable or nop
...
return setmetatable({
...
functionVariable = functionVariable,
...
}, Objectmt)
end
When I deepcopy this object using this
local function deepcopy(t)
if t == nil then return nil end
if type(t) == 'table' then
local copy = {}
for k, v in pairs(t) do
copy[k] = deepcopy(v)
end
setmetatable(copy, deepcopy(getmetatable(t)))
return copy
else -- number, string, boolean, etc
return t
end
end
and load in the object using this
for k, v in pairs(state.objectsTable) do objectsTable[k] = v end
the function variable is totally wrong. It isn't the function that was passed into the object anymore and yeilds unexpected results
There are a lot of things that could be going wrong, and not enough information to say for sure. However, there are some things I can see that could be wrong with your copy, and one in particular that seems problematic.
Your deepcopy function will copy the metatable of the object:
-- snip...
setmetatable(copy, deepcopy(getmetatable(t)))
-- ...
However, it is a fairly common practice for objects of the same type to share the same metatable, and moreover, your code seems to do this (although without seeing how Objectmt is defined, it isn't clear). Other code can then, for example, determine if something is an object by doing:
function isObject(obj)
return getmetatable(obj)==Objectmt
end
This will fail for your copy, because the metatable is no longer the same (even if it has the same contents).
This could be fixed by having a different version of deepcopy (or modifying the existing one) to reuse the metatable:
-- snip...
setmetatable(copy, getmetatable(t))
-- ...
If that is not the problem, then are are some other things to consider:
Your deepcopy function does not copy table keys. In some cases copying keys could be important, but that doesn't seem to be the case for any of the code you've shown.
Your deepcopy function will not copy functions. This could be important if you use functions with mutable upvalues. Again, this isn't the case for any of the code you've shown.
It is possible that there are other tables besides the metatable that ought to be copied by reference rather than by value. To know which is appropriate, you must understand the way they are used.
There could be userdata or other less common types (e.g. coroutines) that are currently being copied by reference that would need to be copied by value. Some things might not be copyable by value.
There might be something in the data you are copying that ought not by copied at all, for example, a unique identifier.
The problem might not be with the copy at all.
A Lua newbie here. Can I store function references as keys in a Lua Table? Something similar to this:
local fn = function() print('hello') end
local my_table = {}
my_table[fn] = 123
This does seem to work fine but I don't know if I can rely on the uniqueness of the function references. Can Lua reuse function references once they are out of scope? Can this create any issues or is it considered a bad practice due to some reason?
Yeah. One of the best things I've encountered in lua is the anything as references property.
There's nothing wrong with the way you are using your keys in the table.
From Lua PiL
Tables in Lua are neither values nor variables; they are objects.You may think of a table as a dynamically allocated object; your program only manipulates references (or pointers) to them. There are no hidden copies or creation of new tables behind the scenes.
In your example, you haven't passed any argument to the function, so basically, it'll be useless in your case to have functions as reference in the program. On the other hand, something like this:
fn1 = function(x) print(x) end
fn2 = function(x) print("bar") end
t[fn1] = "foo"
t[fn2] = "foo"
for i, v in pairs(t) do i(v) end
does have its uses.
Can Lua reuse function references once they are out of scope?
As long as your parent table is in scope, yes. Since tables are created and manipulated but not copied, so there isn't a chance that your function reference can be deprecated from the table index memory. I'll edit this answer later after trying it out actually too.
Can this create any issues or is it considered a bad practice due to some reason?
It's just considered a bad practise because users familiar with other languages, like C, python etc. tend to have array in mind when reading tables. In lua you have no such worries, and the program will work perfect.
I don't know if I can rely on the uniqueness of the function references.
Why?
The uniqueness of the function references depends on Lua version.
Lua 5.2 manual says:
a function definition may not create a new value; it may reuse some previous value if there is no observable difference to the new function
Example:
-- 10 different function references on Lua 5.1
-- The same function reference for Lua 5.2
local j
for i = 1, 10 do
print(function() print(j) end)
end
-- 10 different function references for any Lua version
for i = 1, 10 do
print(function() print(i) end)
end
So, the rule is: create different closures to get different references.
You can do that, function will remain in the same place of memory until it is destroyed (by garbage collector).
You can try in interactive lua:
> fn = function() print('hello') end
> print(fn)
function: 0x9d058d0
> fn2 = function() print('hello') end
> print(fn2)
function: 0x9d05ee8
> fn2=fn
> print(fn2)
function: 0x9d058d0
> print(function() print('hello') end)
function: 0x9d068a8
> print(function() print('hello') end)
function: 0x9d06bf8
Remember that if fn is local it'll be garbage collected when goes out of scope. In your case it shouldn't be a problem as my_table is local in the same block. See Lua documentation on local variables.
This does seem to work fine but I don't know if I can rely on the uniqueness of the function references.
Every function() end statement creates a new closure. The actually code of a function will be reused if it comes from the same constructor:
for i=1,100 do
t[function() print(i) end] = i -- this function body will be reused
end
But each closure will be unique, and that's what matters for your reference.
Can Lua reuse function references once they are out of scope?
Lua's not going to collect fn as long as it's used as a key in my_table. If my_table goes out of scope, too, such that both table and function get collected, then Lua reusing the reference wouldn't affect you. So either way, you're good.