Last active
March 23, 2021 13:06
-
-
Save mt-inside/05aed0179754b4cd234783e65bc648c9 to your computer and use it in GitHub Desktop.
Used in a blog!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "fmt" | |
type event int | |
const ( | |
push event = iota | |
coin event = iota | |
) | |
type state int | |
const ( | |
locked state = iota | |
unlocked state = iota | |
) | |
func main() { | |
s := locked | |
testEvents := []event{push, coin, push, push, coin, push, coin, coin, coin, push, push} | |
for _, e := range testEvents { | |
if s == locked { | |
if e == push { | |
sideEffect("ouch") | |
} else if e == coin { | |
sideEffect("green light") | |
s = unlocked | |
} | |
} else if s == unlocked { | |
if e == push { | |
sideEffect("click") | |
s = locked | |
} else if e == coin { | |
sideEffect("cha-ching") | |
} | |
} | |
} | |
} | |
func sideEffect(s string) { | |
fmt.Println(s) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "fmt" | |
type event int | |
const ( | |
push event = iota | |
coin event = iota | |
) | |
type stateFn func(event) stateFn | |
func main() { | |
t := newTurnstyle() | |
testEvents := []event{push, coin, push, push, coin, push, coin, coin, coin, push, push} | |
for _, e := range testEvents { | |
t.dispatch(e) | |
} | |
fmt.Println("Day's takings:", t.takings) | |
} | |
type turnstyle struct { | |
state stateFn | |
takings int | |
} | |
func newTurnstyle() *turnstyle { | |
t := &turnstyle{takings: 0} | |
t.state = t.stateLocked | |
return t | |
} | |
func (t *turnstyle) dispatch(e event) { | |
next := t.state(e) | |
if next != nil { | |
t.state = next | |
} | |
} | |
func (t *turnstyle) stateLocked(e event) stateFn { | |
switch e { | |
case push: | |
sideEffect("ouch") | |
return nil | |
case coin: | |
sideEffect("green light") | |
t.takings = t.takings + 1 | |
return t.stateUnlocked | |
} | |
panic("unknown event") | |
} | |
func (t *turnstyle) stateUnlocked(e event) stateFn { | |
switch e { | |
case push: | |
sideEffect("click") | |
return t.stateLocked | |
case coin: | |
sideEffect("cha-ching") | |
t.takings = t.takings + 1 | |
return nil | |
} | |
panic("unknown event") | |
} | |
func sideEffect(s string) { | |
fmt.Println(s) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "fmt" | |
type event int | |
const ( | |
push event = iota | |
coin event = iota | |
) | |
type stateFn func(event) stateFn | |
func main() { | |
/* This example is called "1-D". | |
* We actually store the "state" as a pointer straight to the function that implements it. | |
* But we could have a state enum and a slice of the funcions (see 2-D) */ | |
s := stateLocked | |
testEvents := []event{push, coin, push, push, coin, push, coin, coin, coin, push, push} | |
for _, e := range testEvents { | |
s = dispatch(s, e) | |
} | |
} | |
func dispatch(s stateFn, e event) stateFn { | |
next := s(e) | |
if next == nil { | |
return s | |
} | |
return next | |
} | |
func stateLocked(e event) stateFn { | |
switch e { | |
case push: | |
sideEffect("ouch") | |
return nil | |
case coin: | |
sideEffect("green light") | |
return stateUnlocked | |
} | |
panic("unknown event") | |
} | |
func stateUnlocked(e event) stateFn { | |
switch e { | |
case push: | |
sideEffect("click") | |
return stateLocked | |
case coin: | |
sideEffect("cha-ching") | |
return nil | |
} | |
panic("unknown event") | |
} | |
func sideEffect(s string) { | |
fmt.Println(s) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "fmt" | |
type event int | |
const ( | |
push event = iota | |
coin event = iota | |
) | |
type state int | |
const ( | |
locked state = iota | |
unlocked state = iota | |
) | |
type stateFn func() (state, bool) | |
func main() { | |
t := newTurnstyle() | |
testEvents := []event{push, coin, push, push, coin, push, coin, coin, coin, push, push} | |
for _, e := range testEvents { | |
t.dispatch(e) | |
} | |
fmt.Println("Day's takings:", t.takings) | |
} | |
type turnstyle struct { | |
takings int | |
state state | |
machine [][]stateFn | |
/* Another way to do this would be | |
* - an interface specifying handler functions for each event | |
* - each "row", ie each state, isn't a slice of functions, but rather an object, providing all th | |
* - see https://golangbyexample.com/state-design-pattern-go/ | |
*/ | |
} | |
func newTurnstyle() *turnstyle { | |
t := &turnstyle{takings: 0, state: locked} | |
t.machine = [][]stateFn{ | |
{t.lockedPush, t.lockedCoin}, | |
{t.unlockedPush, t.unlockedCoin}, | |
} | |
return t | |
} | |
func (t *turnstyle) dispatch(e event) { | |
fn := t.machine[t.state][e] | |
next, transition := fn() | |
if transition { | |
t.state = next | |
} | |
} | |
func (t *turnstyle) lockedPush() (state, bool) { | |
sideEffect("ouch") | |
return 0, false | |
} | |
func (t *turnstyle) lockedCoin() (state, bool) { | |
sideEffect("green light") | |
t.takings = t.takings + 1 | |
return unlocked, true | |
} | |
func (t *turnstyle) unlockedPush() (state, bool) { | |
sideEffect("click") | |
return locked, true | |
} | |
func (t *turnstyle) unlockedCoin() (state, bool) { | |
sideEffect("cha-ching") | |
t.takings = t.takings + 1 | |
return 0, false | |
} | |
func sideEffect(s string) { | |
fmt.Println(s) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment