I gave this a look and it's pretty neat. I like how the initial example is easy to grasp, but then you keep reading and reading and discovering advanced stuff if you need it.
I've got some minor syntax suggestions for you to consider:
1- Using the event name as keys of the "events" table:
So this:
Code: Select all
local fsm = machine.create({
initial = 'green',
events = {
{ name = 'warn', from = 'green', to = 'yellow' },
{ name = 'panic', from = 'yellow', to = 'red' },
{ name = 'calm', from = 'red', to = 'yellow' },
{ name = 'clear', from = 'yellow', to = 'green' }
}
})
Becomes:
Code: Select all
local fsm = machine.create({
initial = 'green',
events = {
warn = { from = 'green', to = 'yellow' },
panic = { from = 'yellow', to = 'red' },
calm = { from = 'red', to = 'yellow' },
clear = { from = 'yellow', to = 'green' }
}
})
Less typing, same info.
2- Putting the callbacks inside the event table, and remove the "on":
Code: Select all
local fsm = machine.create({
initial = 'green',
events = {
warn = { from = 'green', to = 'yellow', enter= function() ... end },
panic = { from = 'yellow', to = 'red', before=function() ... end },
calm = { from = 'red', to = 'yellow', after=function() ... end },
clear = { from = 'yellow', to = 'green', leave=function() ... end }
}
})
3- By the way, I'm not sure about the difference between "enter" vs "before" and "after" vs "leave". Maybe adding a phrase saying "The difference between enter and before is ..." right after explaining the callbacks would help.
4- Remove "magical" callback function names
By magical I'm referring to these. They require too much mental work IMHO:
Code: Select all
fsm.ongreen = nil -- was this on enter, or onBefore? If I change ongreen, what happens if I invoke onentergreen?
fsm.onyellow = nil
fsm.onred = nil
fsm.onchangestate = function(event, from, to) print(to) end
If you transform your events into call-able tables, you can have a slightly longer names, but with no magic. I consider this better because there are no rules to remember. Let the code explains itself:
Code: Select all
fsm.green.enter = nil
fsm.yellow.enter = nil
fsm.red.enter = nil
fsm.change = function(event, from, to) print(to) end -- instead of onchangestate
Nice thing: you can define the callbacks using Lua's regular function definition syntax if you want:
Code: Select all
function fsm.yellow.enter(...)
...
end
Having fsm.yellow as a table has other advantages. For example you could define fsm.yellow.draw, fsm.red.draw, and then just do fsm.current.draw().
This is all I could think for now.
Regards!
EDIT: I forgot to mention that I saw it's integrated with TravisCI! That's very cool! But out of curiosity: why "erlang"?