Some question about "Closure" in Lua - lua

Here's my code, I confuse the local variable 'count' in the return function(c1,c2) with memory strack and where does they store in?
function make_counter()
local count = 0
return function()
count = count + 1
return count
end
end
c1 = make_counter()
c2 = make_counter()
print(c1())--print->1
print(c1())--print->2
print(c1())--print->3
print(c2())--print->1
print(c2())--print->2

in the return function(c1,c2) with memory strack and where does they store in?
It's stored in the closure!
c1 is not a closure, it is the function returned by make_counter(). The closure is not explicitly declared anywhere. It is the combination of the function returned by make_counter() and the "free variables" of that function. See closures # Wikipedia, specifically the implementation:
Closures are typically implemented with a special data structure that contains a pointer to the function code, plus a representation of the function's lexical environment (e.g., the set of available variables and their values) at the time when the closure was created.

I'm not quite sure what you're asking exactly, but I'll try to explain how closures work.
When you do this in Lua:
function() <some Lua code> end
You are creating a value. Values are things like the number 1, the string "string", and so forth.
Values are immutable. For example, the number 1 is always the number 1. It can never be the number two. You can add 1 to 2, but that will give you a new number 3. The same goes for strings. The string "string" is a string and will always be that particular string. You can use Lua functions to take away all 'g' characters in the string, but this will create a new string "strin".
Functions are values, just like the number 1 and the string "string". Values can be stored in variables. You can store the number 1 in multiple variables. You can store the string "string" in multiple variables. And the same goes for all other kinds of values, including functions.
Functions are values, and therefore they are immutable. However, functions can contain values; these values are not immutable. It's much like tables.
The {} syntax creates a Lua table, which is a value. This table is different from every other table, even other empty tables. However, you can put different stuff in tables. This doesn't change the unique value of the table, but it does change what is stored within that table. Each time you execute {}, you get a new, unique table. So if you have the following function:
function CreateTable()
return {}
end
The following will be true:
tableA = CreateTable()
tableB = CreateTable()
if(tableA == tableB) then
print("You will never see this")
else
print("Always printed")
end
Even though both tableA and tableB are empty tables (contain the same thing), they are different tables. They may contain the same stuff, but they are different values.
The same goes for functions. Functions in Lua are often called "closures", particularly if the function has contents. Functions are given contents based on how they use variables. If a function references a local variable that is in scope at the location where that function is created (remember: the syntax function() end creates a function every time you call it), then the function will contain a reference to that local variable.
But local variables go out of scope, while the value of the function may live on (in your case, you return it). Therefore, the function's object, the closure, must contain a reference to that local variable that will cause it to continue existing until the closure itself is discarded.
Where do the values get stored? It doesn't matter; only the closure can access them (though there is a way through the C Lua API, or through the Lua Debug API). So unlike tables, where you can get at anything you want, closures can truly hide data.

Lua Closures can also be used to implement prototype-based classes and objects. Closure classes and objects behave slightly differently than normal Lua classes and their method of invocation is somewhat different:
-- closure class definition
StarShip = {}
function StarShip.new(x,y,z)
self = {}
local dx, dy, dz
local curx, cury, curz
local engine_warpnew
cur_x = x; cur_y = y; cur_z = z
function setDest(x,y,z)
dx = x; dy=y; dz=z;
end
function setSpeed(warp)
engine_warpnew = warp
end
function self.warp(x,y,z,speed)
print("warping to ",x,y,x," at warp ",speed)
setDest(x,y,z)
setSpeed(speed)
end
function self.currlocation()
return {x=cur_x, y=cur_y, z=cur_z}
end
return self
end
enterprise = StarShip.new(1,3,9)
enterprise.warp(0,0,0,10)
loc = enterprise.currlocation()
print(loc.x, loc.y, loc.z)
Produces the following output:
warping to 0 0 0 at warp 10
1 3 9
Here we define a prototype object "StarShip" as an empty table.
Then we create a constructor for the StarShip in the "new" method. The first thing it does is create a closure table called self that contains the object's methods. All methods in the closure (those defined as 'function self.') are "closed" or defined for all values accessible by the constructor. This is why it's called a closure. When the constructor is done it returns the closure object "return self".
A lot more information on closure-based objects is available here:
http://lua-users.org/wiki/ObjectOrientationClosureApproach

Related

Why I can use a function to set a table index using arguments but i can't set a varble passed as a parameter

im new to lua (and programming 😅)
I would like to know why I can use a function to set a table index using arguments but i can't set a varble passed as a parameter like this :
variable = 1
function f(v)
v = 2
end
f(variable)
print(variable)
--prints 1
function f(t,i)
t[i] = 2
end
f(table,index)
print(table[1])
--prints 2
From the Lua manual:
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
In your example variable is a number value which is none one of the mentioned types. Hence it is copied by value, not by reference.
So in
variable = 1
function f(v)
v = 2
end
f(variable)
v is a copy of variable, local to f. Changing v does not affect variable.
In
function f(t,i)
t[i] = 2
end
f(table,index)
print(table[1])
on the other hand, t is a reference to the same table, table refers to. Hence modifying t modifies the referred table.

What does closure function mean for Lua?

As per the guide(https://www.tutorialspoint.com/lua/lua_quick_guide.htm),
which says that:
array = {"Lua", "Tutorial"}
function elementIterator (collection)
local index = 0
local count = #collection
-- The closure function is returned
return function ()
index = index + 1
if index <= count
then
-- return the current element of the iterator
return collection[index]
end
end
end
for element in elementIterator(array)
do
print(element)
end
What does closure function mean for Lua?
In Lua, any function is a closure. In a narrower sense, a closure is an anonymous function like the returned function in your example.
Closures are first-class: they can be assigned to variables, passed to functions and returned from them. They can be both keys and values in Lua tables.
Unlike PHP or C++, closures have access to all variables in local scope—upvalues (in your example, index and count, which keep the iterator state, and also collection) with no need to declare upvalues explicitly. Upvalues survive when code execution leaves the block where they were set.
You cannot write an iterator without a closure (or a subroutine). In your example (a simple iterator), elementIterator is a function that receives a table and returns another function, a closure. This returned closure is called again and again by the generic for instruction until it returns nil.
You may find this paper interesting: https://www.lua.org/doc/jucs17.pdf.

Lua - Why don't Global variables need declarations?

According to Lua's manual
Global variables do not need declarations. You simply assign a value to a global variable to create it. It is not an error to access a non-initialized variable; you just get the special value nil as the result
I think declaration is good, it makes thing more manageable. Why did Lua skip declarations for Global variables? I guess they have a good reason but I don't know why.
What if I make this mistake
-- Activation Code
function TestLoco:OnActivate()
self.MyGlobal = "ABC"; --Init the global variable
end
-- Run every tick
function TestLoco:OnTick()
self.MyGIobaI = "BCD"; --Edit the global variable at every tick, but I mistake 'I' with 'l'
end
-- Call when I click the mouse
function TestLoco:OnClick()
Debug.Log(self.MyGlobal); --This print "ABC", but It should be "BCD", what if I don't notice this?
end
Because Lua has no classes. self.MyGlobal is not a global variable, it is a field in the table passed via the self parameter. The syntax is equivalent to self["MyGlobal"]. For a "true" global variable assignment (e.g. x = 0), it is equivalent to _G["x"] = 0, where _G is the global environment table.
Since Lua has no notion of classes, the type of self is simply a table. The syntax you use for specifying a "method" is just a syntactic shortcut to this:
TestLoco.OnActivate = function(self)
self["MyGlobal"] = "ABC";
end
It's just a function that assigns a field in a table. It could be called with potentially any table, hence it cannot verify the table actually should have that field.
However, Lua offers some pretty good run-time customisable checking via metatables. If you build a table specifying the "class" of a table, you can assign a metatable to every table that checks the assignment each time if it assigns to a field that you actually "declared".

Dumping lua func with arguments

Is it possibly to dump the Lua table including function arguments?
If so, how can I do it?
I have managed to dump tables and function with addresses, but I haven't been able to figure out a way to get function args, i have tried different methods, but no luck.
So I want to receive them truth dumping tables and function plus args of the function.
Output should be something like this: Function JumpHigh(Player, height)
I don't know if it is even possible, but would be very handy.
Table only stores values.
If there's function stored in a table, then it's just a function body, there's no arguments. If arguments were applied, table would store only final result of that call.
Maybe you're talking about closure - function returned from other function, capturing some arguments from a top level function in a lexical closure? Then see debug.getupvalue() function to check closure's content.
Is this something what you're asking?
local function do_some_action(x,y)
return function()
print(x,y)
end
end
local t = {
func = do_some_action(123,478)
}
-- only function value printed
print "Table content:"
for k,v in pairs(t) do
print(k,v)
end
-- list function's upvalues, where captured arguments may be stored
print "Function's upvalues"
local i = 0
repeat
i = i + 1
local name, val = debug.getupvalue(t.func, i)
if name then
print(name, val)
end
until not name
Note that upvalues stored is not necessary an argument to a toplevel function. It might be some local variable, storing precomputed value for the inner function.
Also note that if script was precompiled into Lua bytecode with stripping debug info, then you won't get upvalues' names, those will be empty.

Lua: Skip variable declaration

I am trying to "Skip" a variable, by either never declaring it or just having it garbage collected immediately, but I don't know if it's possible.
Example:
function TestFunc()
return 1, 2
end
function SecondFunction()
local nodeclare, var = TestFunc()
end
Basically what I wanted was for "nodeclare" to not even exist. So if I did print(nodeclare, var) it would do nil, 2.
The same thing would be if I was doing a pairs loop and I didn't need to use the keyvalue.
Is there some special thing I can put as the variable name for this to happen? If say I was doing a pairs loop over 100 values, would that even have a signifigant impact?
First of all, variables are not garbage collected, objects are. In this case, there's nothing to garbage collect.
However, let's say that TestFunc was creating objects (say, tables):
function TestFunc()
return {1}, {2}
end
function SecondFunction()
local nodeclare, var = TestFunc()
end
Now nodeclare is referencing a table returned by TestFunc. That's an object, allocated on the heap, that we don't want hanging around forever.
That object will eventually be collected if there is nothing left referring to it. In your case, as soon as SecondFunction returns, the local nodeclare goes out of scope and goes away. As long as there's nothing else referencing that table, the table will be collected (during next collection cycle).
You can avoid declaring nodeclare entirely by skipping the first return value of TestFunc like this:
local var = select(2, TestFunc())
However, when you're talking about a temporary local variable, as in your example, you normally just create the temporary variable then ignore it. This avoids the overhead of the call to select. Sometimes you use a variable name that indicates it's trash:
local _, var = TestFunc()
If say I was doing a pairs loop over 100 values, would that even have a signifigant impact?
None whatsoever. You're just continually overwriting the value of a local variable.
What impact do you mean exactly? Memory? Performance?
According to the Programming in Lua book, you can sort of skip the second return value, but not ignore the first and use the second:
x,y = foo2() -- x='a', y='b'
x = foo2() -- x='a', 'b' is discarded
x,y,z = 10,foo2() -- x=10, y='a', z='b'

Resources