Skip to content

Instantly share code, notes, and snippets.

@sshirokov
Created July 21, 2009 05:37
Show Gist options
  • Save sshirokov/151145 to your computer and use it in GitHub Desktop.
Save sshirokov/151145 to your computer and use it in GitHub Desktop.
A borderline DSL for describing simple state machines in python
class State(object):
transitions = []
def __init__(self, *transitions_or_data):
if len(transitions_or_data) and reduce(lambda acc, e: acc and type(e) == Transition, transitions_or_data, True):
type(self).transitions = transitions_or_data
else:
self.data = {
1: lambda: transitions_or_data[0],
0: lambda: None,
}.get(len(transitions_or_data), lambda: transitions_or_data)()
def transition(self, data):
transition = reduce(lambda acc, transition: \
acc or (transition.is_valid(data) and transition),
self.transitions,
None)
if transition:
self.data = transition.callback(self.data)
return transition.next(data)(self.data)
return None
class Transition(object):
def __init__(self, test, next_state, callback = lambda data: data):
self.test = test
self.next_state = next_state
self.callback = callback
def is_valid(self, data):
if not self.test: return True
return self.test(data)
def next(self, data):
return self.next_state
def __repr__(self):
return "<Transition(%s%s )>" % ((self.test and " ") or " Default, ", self.next_state)
def make_states(*names):
return map(lambda name: type(name, (State,), {}), names)
WaitingForOne, WaitingForTwo, OneTwoDone = make_states("WaitingForOne",
"WaitingForTwo",
"OneTwoDone")
def touch_data(d):
print "I can see:", d
return d + " (Touched)"
WaitingForOne(
Transition(lambda d: d == 1, WaitingForTwo),
Transition(None, WaitingForOne))
WaitingForTwo(
Transition(lambda d: d == 2, OneTwoDone, callback = touch_data),
Transition(None, WaitingForTwo))
state = WaitingForOne("Keep it secret, keep it safe")
print "In initial:", state
state = state.transition(3) #Will still be WaitingForOne
state = state.transition(1) #Becomes WaitingForTwo
state = state.transition(1) #Stays WaitingForTwo
state = state.transition(2) #Becomes OneTwoDone
print "Finished in:", state
print "Data:", state.data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment