Skip to content

Instantly share code, notes, and snippets.

Last active June 1, 2023 15:53
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
State machine with generators
Lamps often have on-off switches that twist clockwise, clicking as they do.
Some such switches have four states, even though the lamp has only two (on, and off).
On these lamps clicking the switch will only cause an on/off transition every other click.
Just looking at the lamp you'll know if it's on, but not if the next click will turn it off.
To reliably interact with such a lamp you will use an algorithm, even in real life.
I use the term strategy to refer to an algorithm expressed with generators like this --
the strategy pattern is useful to abstract an algorithm from the representation of the data.
For more about lamps:
function* toggleStrategy(lamp) {
const wasOn = lamp.on;
while (lamp.on === wasOn) {
yield 'click';
assertEqual(2, useLamp(toggleStrategy, 0b00));
assertEqual(1, useLamp(toggleStrategy, 0b01));
assertEqual(2, useLamp(toggleStrategy, 0b10));
assertEqual(1, useLamp(toggleStrategy, 0b11));
function* onStrategy(lamp) {
while (!lamp.on) {
yield 'click';
assertEqual(2, useLamp(onStrategy, 0b00));
assertEqual(1, useLamp(onStrategy, 0b01));
assertEqual(0, useLamp(onStrategy, 0b10));
assertEqual(0, useLamp(onStrategy, 0b11));
function useLamp(strategy, initialState) {
const facade = ({ get on() { return state <= 0b10 }});
let state = initialState;
let clicks = 0;
for (const action of strategy(facade)) {
switch(action) {
case 'click':
state = (state + 0b01) & 0b11;
throw new Error(`unknown {action: ${action}}`);
return clicks;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment