Getting func(y) with Channels
Here’s a little golang puzzle
Take a look at the function below that computes a mystery value for the function $f(x)$. Any idea what the function is? Take a close look at the first line where we create a channel. Notice that the channel isn’t some boring int
or string
channel. No, this is a channel of type func(int, chan int, chan bool)
. Wait what??? That’s right, this channel takes a function that takes an integer and two channels as function parameters. We define such a function, x
, right aftewards.
func mystery(n int) int {
fc := make(chan func(int, chan int, chan bool), 1)
x := func(v int, pipe chan int, done chan bool) {
if v > (n - 1) {
done <- true
}
pipe <- (v)
}
done := make(chan bool, 1)
pipe := make(chan int, n)
fc <- x
go func(fc chan func(int, chan int, chan bool), pipe chan int, done chan bool) {
start := 0
for {
f := <-fc
f(start, pipe, done)
fc <- f
start++
}
}(fc, pipe, done)
<-done
var sigma int = 0
for {
var y int
var ok bool
select {
case y, ok = <-pipe:
sigma += y
default:
fmt.Printf("empty pipe, break\n")
break
}
if ok {
} else {
fmt.Printf("sigma = %d\n", sigma)
break
}
}
return sigma
}
Still stumped on the composition of $f(x)$? Answer:
$$\text{ }f(x) = \sum_{n=0}^n{\frac{n(n+1)}{2}} $$
Bonus question, how would you modify the code above to compute:
$$\text{ }f(x) = \sum_{n=0}^n{\frac{n(n+1)(2n+1)}{6}} $$
hint: we could refactor the code to make a function that transforms our $x$ value.
func mystery(n int, fx func(int) int) int {
fc := make(chan func(int, chan int, chan bool), 1)
x := func(v int, pipe chan int, done chan bool) {
if v > (n - 1) {
done <- true
}
pipe <- (v)
}
done := make(chan bool, 1)
pipe := make(chan int, n)
fc <- x
go func(fc chan func(int, chan int, chan bool), pipe chan int, done chan bool) {
start := 0
for {
f := <-fc
f(start, pipe, done)
fc <- f
start++
}
}(fc, pipe, done)
<-done
var sigma int = 0
for {
var y int
var ok bool
select {
case y, ok = <-pipe:
sigma += fx(y)
default:
fmt.Printf("empty pipe, break\n")
break
}
if ok {
} else {
fmt.Printf("sigma = %d\n", sigma)
break
}
}
return sigma
}