Skip to content

Instantly share code, notes, and snippets.

@montanaflynn
Last active October 25, 2015 21:52
Show Gist options
  • Save montanaflynn/d913bb3828fe5e5cb290 to your computer and use it in GitHub Desktop.
Save montanaflynn/d913bb3828fe5e5cb290 to your computer and use it in GitHub Desktop.
Statistics with channels and first-class functions
package main
import (
"log"
)
type fchan chan float64
type ichan chan int
type datafun func(Data, ichan, fchan)
type Data []float64
func (d Data) Analyze(fn datafun) float64 {
// Length of data used to track progress
dl := len(d)
// Make the int chan which is used for
// showing progress, the buffer is the
// amount of items in the data
ci := make(ichan, dl)
// This float64 chan will get the final
// result so it only needs a buffer of 1
cf := make(fchan, 1)
fn(d, ci, cf)
// Since we know the amount of items in the
// data we know the amount of progress reports
// sent on the ci channel so watch for them all
for i := 0; i < dl; i++ {
// When we get a report send it and the
// total to our progress helper func
progress(dl, <-ci)
}
// Only return when we get the final result
return <-cf
}
func mean(d Data, ci ichan, cf fchan) {
var sum float64
for i, n := range d {
sum += n
// Show progress by sending to ichan
ci <- i
}
// When we're done send the final result
cf <- sum / float64(len(d))
// And close down the channels, although
// I think they would be garbage collected
close(ci)
close(cf)
}
func progress(t int, c int) {
log.Println(c+1, "/", t)
}
func makeFloatSlice(c int) []float64 {
fslice := make([]float64, 0, c)
for i := 0; i < c; i++ {
f := float64(i)
fslice = append(fslice, f)
}
return fslice
}
func main() {
var d Data = makeFloatSlice(10000)
log.Println(d.Analyze(mean))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment