Skip to content

Instantly share code, notes, and snippets.

@mattdeboard
Last active August 29, 2015 14:08
Show Gist options
  • Save mattdeboard/b03b25986255eead6c68 to your computer and use it in GitHub Desktop.
Save mattdeboard/b03b25986255eead6c68 to your computer and use it in GitHub Desktop.
Super naive impl of a Clojure-style atom in CoffeeScript
class Atom
__state:
initial: null
current: null
constructor: (state) ->
@__state['current'] = state
@__state['initial'] = state
_cloneState: (phase = 'current') ->
###
Returns a copy of a particular phase (i.e. either current or initial)
of the atom state.
###
obj = @__state[phase]
if typeof(obj) == 'object'
tmp_obj = {}
for k, v of obj
tmp_obj[k] = v
return tmp_obj
else if typeof(obj) == 'array'
return obj.slice()
else
return obj
_deref: ->
@_cloneState()
_swap: (fn, args...) ->
curr_state = @_deref()
@__state['last'] = curr_state
args.splice 0, 0, curr_state
@__state['current'] = fn.apply(fn, args)
@
_reset: (new_val = null) ->
new_state = @_cloneState('initial')
if new_val?
new_state = new_val
@__state['current'] = new_state
@
deref = (atom) ->
###
Return a copy of the current state of the atom. Modifications to the
value returned will not update the state of the atom. Use 'swap' for
that.
###
atom._deref()
swap = (atom, fn, args...) ->
###
Transform the current state of the atom by calling 'fn' with arguments
'args'.
###
atom._swap fn, args
reset = (atom, new_val) ->
###
Set the value of atom without regard to its current value. If
'new_val' is not provided, then resets value of atom to its
initial value.
###
atom._reset(new_val)
app_state = new Atom
foo: "bar"
baz: "qux"
###
Example:
Adds a new key to 'app_state'.
Obviously this requires some knowledge of the shape of the app state in the
atom.
###
_func_for_swap = (state_val) ->
# 'state_val' will be the value of a dereferenced atom.
state_val['quux'] = 'quuux'
state_val
# Look at the current state
console.log deref(app_state)
# Modify the atom state
swap app_state, _func_for_swap
# Should have 'quux' key now
console.log deref(app_state)
# Set it back to its original value
reset app_state
# Should match initial state
console.log deref(app_state)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment