Does lua have an "event handler" build in or does it have a lib available to do that?
So that, an example, when "a = 100" an event happens.
Something else rather than using:
while true do
if a == 100 then
[...]
break;
end
end
Or simply adding a sleep to it. The "while true do" is just an example but its a terrible one.
Lua operates in a single-thread, so any checking must be explicitly performed by your code.
The act of performing code immediately upon a variable changing is known as "watching".
If you are programming in an environment where a set of code is run every frame (such as a game), you can check manually. For example:
WatchedVariables = {
a = 5,
b = 22,
}
WatchedVariables_cache = {}
for k,v in pairs(WatchedVariables) do
WatchedVariables_cache[k] = v
end
function OnFrame()
print("NEXT FRAME! (possibly 1 second later or something)")
for k,v in pairs(WatchedVariables) do
local v_old = WatchedVariables_cache[k]
if v ~= v_old then
-- this is the "callback"
print(tostring(k).." changed from "..tostring(v_old).." to "..tostring(v))
WatchedVariables_cache[k] = v
end
end
end
function SomeFunctionThatOperatesSomeTime()
print("about to change a, brother!")
WatchedVariables.a = -7
print("a is changed")
end
Upon the next frame, the callback code (the print) will be executed.
The disadvantage of this approach is that the callback code is not printed immediately after WatchedVariables.a
is set to -7
, that is: the output will be:
about to change a, brother!
a is changed
NEXT FRAME! (possibly 1 second later or something)
a changed from 5 to -7
To prevent this potentially undesired behaviour, a setter function can be used, for example:
MyObject = {
_private_a = 5,
set_a = function(self, new_value_of_a)
self._private_a = 5
-- callback code
print("a set to "..tostring(new_value_of_a))
end,
get_a = function(self)
return self._private_a
end
}
function SomeFunctionThatOperatesSomeTime()
print("about to change a, brother!")
MyObject:set_a(-7)
print("a is changed")
end
The output of this code shows that the callback runs immediately:
about to change a, brother!
a set to -7
a is changed
To make this more comfortable, Lua provides metatables that make such behaviour transparent to the programmer. Example:
MyObject = {
__privates = {
a = 5,
}
}
MyObject_meta = {
__index = function(self, k)
return rawget(self, "__privates")[k]
end,
__newindex = function(self, k, v)
rawget(self, "__privates")[k] = v
-- callback code
print("a set to "..tostring(v))
end,
}
setmetatable(MyObject, MyObject_meta)
function SomeFunctionThatOperatesSomeTime()
print("about to change a, brother!")
MyObject.a = -7
print("a is changed")
end
The output of this code will be the same as the previous example:
about to change a, brother!
a set to -7
a is changed
Here's an implementation for your example case:
MyObject = {
__privates = {
a = 5,
}
__private_callback = function(self, k, ov, v)
if k == "a" and v == "100" then
print("a is 100!")
end
end
}
MyObject_meta = {
__index = function(self, k)
return rawget(self, "__privates")[k]
end,
__newindex = function(self, k, v)
local privates = rawget(self, "__privates")
local ov = privates[k]
privates[k] = v
rawget(self, "__private_callback")(self, k, ov, v)
end,
}
setmetatable(MyObject, MyObject_meta)
function SomeFunctionThatOperatesSomeTime()
MyObject.a = -7 -- prints nothing
MyObject.a = 100 -- prints "a is 100!"
MyObject.a = 22 -- prints nothing
end
Why are the variables __privates
and __private_callback
prefixed with two underscores? It is convention to prefix private members that should not be accessed in typical programming situations with two underscores. If you familiar with object-oriented methodology and it's implementation in languages such as Java and C++, you will understand how it is similar to the private
and protected
keywords.
If you are familiar with the C# language, you may see how the set_a
/get_a
and metatable implementations are similar to accessors (set
/get
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With