Created
August 13, 2012 22:23
-
-
Save gatlin/3344489 to your computer and use it in GitHub Desktop.
Concepts from Orc applied in 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 main | |
import ( | |
"fmt" | |
"github.com/gatlin/go-orc" | |
"net/http" | |
"time" | |
) | |
/* | |
* a nifty example | |
*/ | |
func main() { | |
// a site is a function which publishes a value asynchronously | |
load_page := orc.Site{ | |
func(url orc.Void, publish orc.Voidchan) { | |
resp, _ := http.Get(url.(string)) | |
defer resp.Body.Close() | |
publish <- url | |
}, | |
} | |
// the built-in Cut function calls multiple sites concurrently and yields | |
// the first return value | |
loaded_first := orc.Cut([]orc.Voidchan{ | |
load_page.Call("http://archlinux.fr"), | |
load_page.Call("http://google.com"), | |
load_page.Call("http://amazon.com"), | |
}) | |
// for now, it's your job to assert types. | |
// Void is interface{} and Voidchan is chan interface{} | |
fmt.Println(loaded_first.(string)) | |
// rtimer publishes `t` after `t` seconds | |
rtimer := orc.Site{ | |
func(t orc.Void, publish orc.Voidchan) { | |
<-time.After(time.Duration(t.(int)) * time.Second) | |
publish <- t | |
}, | |
} | |
// this site wraps fmt.Println | |
site_print := orc.Site{ | |
func(msg orc.Void, publish orc.Voidchan) { | |
fmt.Println(msg) | |
publish <- nil | |
}, | |
} | |
// sites can be recursive if pre-declared | |
// metronome also shows a nifty heart-beat pattern in Orc which could be | |
// useful for fault-tolerance in distributed computations | |
var metronome orc.Site | |
metronome = orc.Site{ | |
func(t orc.Void, publish orc.Voidchan) { | |
orc.Merge([]orc.Voidchan{ | |
site_print.Call("tick"), | |
rtimer.Call(t).ForEachDo(metronome), | |
}) | |
}, | |
} | |
<-metronome.Call(1) | |
} |
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 orc | |
/* | |
* end run around the type system | |
*/ | |
type Void interface{} | |
type Voidchan chan Void | |
/* | |
* Sites, functions which remote / asynchronous services | |
*/ | |
type Site struct { | |
Fn func(arg Void, out Voidchan) | |
} | |
func (s Site) Call(arg Void) Voidchan { | |
out := make(Voidchan, 1) | |
go s.Fn(arg, out) | |
return out | |
} | |
/* | |
* Orc inspired functions | |
*/ | |
func Merge(cs []Voidchan) Voidchan { | |
combined := make(Voidchan, cap(cs)) | |
for _, c := range cs { | |
go func(ch Voidchan) { | |
for v := range ch { | |
combined <- v | |
} | |
return | |
}(c) | |
} | |
return combined | |
} | |
func (self Voidchan) ForEachDo(site Site) Voidchan { | |
for i := 0; i < cap(self); i++ { | |
s := <-self | |
<-site.Call(s) | |
} | |
return make(Voidchan, 1) | |
} | |
func (self Voidchan) WithFirstDo(fn Site) { | |
v := <-self | |
<-fn.Call(v) | |
} | |
func Cut(cs []Voidchan) Void { | |
c := make(Voidchan, 1) | |
Merge(cs).WithFirstDo(Site{ | |
func(arg Void, out Voidchan) { | |
c <- arg | |
out <- nil | |
}, | |
}) | |
return <-c | |
} | |
Above comment is now obsolete :)
If anyone does view this, Sites are objects because I'd like to abstract how computations are orchestrated from where they are happening; Site might become an interface adhered to by a LocalSite or RemoteSite object. Stay tuned?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Causes a deadlock but this is the basic idea, even if it's faulty for now.