Code Monkey home page Code Monkey logo

notifitable's Introduction

Notifitable

Lua tables that notify you when values have changed.

The Notifitable library exposes a single function that creates or wraps a Lua table. The resulting table has a registerForChange() method that lets you specify one or more callbacks to invoke when certain keys in the table get a new value.

Simple Usage

-- Call the function whatever you like
local notifitable = require('notifitable')
local t1 = notifitable()

function yellOnValueChanges(key,newval,oldval)
  print("The key", key, "just changed from", oldval, "to", newval)
end

t1:registerForChange( 'foo', yellOnValueChange )

t1.foo = 42 --> "The key foo just changed from nil to 42"
t1.foo = 42 --  (no callback for same value)
t1.bar = 99 --  (no callback for non-registered keys)
t1.foo = 17 --> "The key foo just changed from 42 to 17"

Wrapping an Existing Table

If you already have a table of information that you want to monitor, pass it to the function:

local prefs = {
  theme = 'dismal',
  socks = false
}
local t2 = notifitable(prefs)
t2:registerForChange( 'theme', yellOnValueChange )
t2.theme = 'bright'           --> "The key theme just changed from dismal to bright"
assert(prefs.theme=='bright') --> The original table is updated…
prefs.theme = "don't do this" --> …but changes to it do not causes notifications

Registering in a Hierarchy

If you have a hierarchy of values you may register for a specific key deep in the chain:

local prefs = notifitable{
  settings = {
    editor = {
      usetabs = true,
      tabsize = 2
    }
  }
}

prefs:registerForChange('settings','editor','usetabs',onTabsChanged)

Internally this replaces each table in the hierarchy with a notifitable wrapper.

Autovivification

You can register for an access path that does not already exist:

local t3 = notifitable() -- an empty table
t3:registerForChange('settings','editor','usetabs',someFunction)

The implementation of this creates notifitable values along the path to that final function. (It might be nice if this was super lightweight, only taking effect if at some point in the future that path was created. This is not the current situation.)

Running Into Trouble

Under happy circumstances the registerForChange() method returns true. However, if you attempt to register for a hierarchical value, but one of the keys in that path exists and is not a table, the registerForChange() method will fail and return nil instead. This is your only indication that the registration could not be accomplished.

local t4 = notifitable{ settings='rainbows' }
local success = t4:registerForChange('settings','editor','usetabs',someFunction)
assert(success) --> FAIL

Removing a Registration

If you have a callback that you no longer wish to have invoked, there is an equivalent unregisterForChange() method on the notifitable.

t:registerForChange('settings','editor','usetabs',someFunction)
-- and then later
t:unregisterForChange('settings','editor','usetabs',someFunction)

Note that this does not 'unwrap' any notifitables along the path that might no longer be needed for registration.

Limitations (aka TODO)

  • It would be nice to be able to perform wildcard registrations at a particular level.
  • It would be nice to not autovivify the full path to a registration, but instead use a lightweight hook.
  • It might be nice to not wrap a table (in order to use __newindex as the hook), but instead require a setter function that took the path and also kicked off notifications on an otherwise-normal table.
  • For simplicity, the order in which callbacks are invoked for the same key is not specified. It might be nice to allow control over this (i.e. first registered is the first invoked).
  • There's no reason to wrap every table on the path down a hierarchy as a notifitable; only the last table in the list needs to support registration.

License

Notifitable is licensed under the MIT License. See the file LICENSE for details.

notifitable's People

Contributors

phrogz avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

tidal-loop

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.