Skip to content

Instantly share code, notes, and snippets.

@jbowles
Created March 23, 2013 15:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbowles/5228042 to your computer and use it in GitHub Desktop.
Save jbowles/5228042 to your computer and use it in GitHub Desktop.
First pass at porting Sate Jacket to Go
//package state_gacket // soft 'g', like state_dʒacket
package main
import (
"fmt"
"reflect"
)
/*
type Metadata struct {
EntryLength int
}
//TODO get this working
func (c Catalog) SetMetadata() {
//catalog_length := len(c)
c.Metadata.EntryLength = len(c.Entry)
return
}
*/
// One big difference from the original: I have created a struct to hold the state values, this changes the function call in that if gacket you much also initialize the States struct as well as the Catalog struct. I may roll this back a simpler data structure where the Catalog.Entry is a map that contains a []string slice (currently it's a map that contains a struct that is a []string slice). It's a subtle difference but I'm following my intuition.
type States struct {
//nil is allowed for slices or pointers, initialize nil by []string{}, which is the default value
values []string
}
type Catalog struct {
//TODO experiment with a meta field by way of Clojure's use of it
//Metadata
Entry map[string]States
}
func (c Catalog) add(s States, entry string, state []string) {
s.values = state
c.Entry[entry] = s
return
}
func (c Catalog) Inspect() {
for k, v := range c.Entry {
fmt.Println(k,v)
}
}
//TODO handle Transitioners and Terminators an Interface
func (c Catalog) Transitioners() []string{
var ts = []string{}
for k,_ := range c.Entry {
if len(c.Entry[k].values) > 0 {
ts = append(ts, k)
}
}
//fmt.Println(ts)
return ts
}
func (c Catalog) Terminators() []string {
var terms = []string{}
for k,_ := range c.Entry {
if len(c.Entry[k].values) == 0 {
terms = append(terms, k)
}
}
//fmt.Println(ts)
return terms
}
//got this from http://play.golang.org/p/rs6kfvRD9M
// and from https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/yQk_g7AjcU8
func Contains(slice interface{}, val interface{}) bool {
sv := reflect.ValueOf(slice)
for i := 0; i < sv.Len(); i++ {
if sv.Index(i).Interface() == val {
return true
}
}
return false
}
func (c Catalog) CanTransition(from_to map[string][]string) (ret bool){
for k,v := range from_to {
_,ok := c.Entry[k]
to := c.Entry[k].values
if ok == false {
ret = false
}else if len(v) == 0{
return false
}else{
//vs := string(v[0])
ret = Contains(to,string(v[0]))
}
}
return ret
}
func main() {
c := Catalog{}
s := States{}
c.Entry = make(map[string]States)
c.add(s,"open",[]string{"closed","error"})
c.add(s,"closed",[]string{"open","error"})
some_more_states := []string{}
entry_name := "error"
c.add(s,entry_name,some_more_states)
c.Inspect()
fmt.Println("Transitioners:",c.Transitioners())
fmt.Println("Terminators:",c.Terminators())
var x = make(map[string][]string)
x["error"] = []string{"open"}
fmt.Println(c.CanTransition(x),"for set:", x)
//can also add State.values like this:
//s.values = []string{"closed","error"}
//c.Entry["open"] = s
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment