How do I detect when a variable changes?

I am currently trying to keep my module away from actual value instances to look cleaner (and perform better). Is there a way I can detect when a local variable changes? If so please tell me how.

2 Likes

You can do some nonsense with metatables to achieve the effect, but it will make your code more complex and non-obvious to tell what is happening—changing a variable triggers some random hidden code somewhere else? Sounds like a recipe for surprises later :slight_smile:

A simpler option is to just always change the variables through a method:

local SetMyVariable
local GetMyVariable
do
  -- hide the variable within this scope so we don't
  -- accidentally set it without our additional function
  local _myVariable = "default"
  function GetMyVariable() return _myVariable end
  function SetMyVariable(value)
    _myVariable = value

    -- here's our "on changed" detection!
    print("my variable was changed to", value)
  end
end

-- usage

print("variable is", GetMyVariable())
SetMyVariable(7) -- prints: my variable was changed to 7

If you truly wanna go ahead despite the warnings…

You can’t detect a variable, but you can detect a value inside a table changing with a proxy table and some metamethods:

local MyVariable = {}
do
  local MyVariableStorage = { value = "default" }
  setmetatable(MyVariable, { __index = MyVariableStorage, __newindex = function(t, k, v)
    if k == "value" then
      MyVariableStorage[k] = v
      -- here's our "on changed" detection!
      print("my variable was changed to", v)
    end
  end })
end

-- usage

print("variable is", MyVariable.value)
MyVariable.value = 7 -- prints: my variable was changed to 7
4 Likes

Well I am using metatables:

local class = setmetatable({ }, module)
class.Value = "gamer" -- How do I detect when a function changes this
1 Like

Again, I’d suggest using getters and setters in that case. Don’t let people access gamer at all, except through GetValue and SetValue.

Anyways, I edited my original response with a way you can do it if you still want to :slight_smile:

1 Like

you can use __newindex to detect changes

local originalTable = {}
local funnyMetatable = setmetatable({},{
    __newindex = function(self,index,value)
        print(self,index,value)
        originalTable[index] = value
    end,
    __index = function(self,index)
        return originalTable[index]
    end
})
funnyMetatable.Value = 1
print(funnyMetatable.Value)
2 Likes

So if I am correct, this would work?:

local function valChanged(): number
    return NotificationsCount
end
local function setVal(): number
    NotificationsAmount += amount
    local new = valChanged()
    return new
end
1 Like

In what context? Which of the two suggested methods are you attempting?

1 Like