Created
March 23, 2013 15:13
-
-
Save jbowles/5228042 to your computer and use it in GitHub Desktop.
First pass at porting Sate Jacket to Go
This file contains hidden or 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 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