Generator/Exponential: Difference between revisions

Content added Content deleted
(→‎{{libheader|libco}}: Add some ugly code to check for memory allocation, and to free memory. C is being an awful language.)
(→‎{{header|Go}}: better implementation. replaced entire program.)
Line 232: Line 232:


=={{header|Go}}==
=={{header|Go}}==
Most direct and most efficient on a single core is implementing generators with closures.
Generators can be implemented directly in Go by a channel fed by a goroutine.

Thus a "function returning a generator" corresponds to a function that creates a channel, starts a goroutine that will send values on the channel, and returns the channel. The function powCh does this, starting a function literal as the goroutine. The returned channel corresponds to a generator.

The "generator that filters..." is implemented without an extra function, simply by creating the channel and starting a (previously declared) function as a goroutine. Here too, the created channel, chF, corresponds to a generator, once the goroutine has be started for it.
<lang go>package main
<lang go>package main


Line 245: Line 241:


// note: exponent not limited to ints
// note: exponent not limited to ints
func powCh(e float64) <-chan float64 {
func newPowGen(e float64) func() float64 {
ch := make(chan float64)
var i float64
go func() {
return func() (r float64) {
r = math.Pow(i, e)
// generate powers of non-negative integers
for i := float64(0); ; i++ {
i++
ch <- math.Pow(i, e)
return
}
}
}()
return ch
}
}


// given two functions af, bf, both monotonically increasing, return a
// this long function name to indicate that the filtering
// new function that returns values of af not returned by bf.
// logic works only because squares and cubes are both
func newMonoIncA_NotMonoIncB_Gen(af, bf func() float64) func() float64 {
// monotonically increasing over the specified domain
a, b := af(), bf()
// of non-negative integers.
return func() (r float64) {
func genMonotonicIncA_NotMonotonicIncB(outCh chan<- float64,
for {
aCh, bCh <-chan float64) {
for a, b := <-aCh, <-bCh; ; {
if a < b {
if a > b {
r = a
b = <-bCh
a = af()
continue
break
} else if a < b {
}
outCh <- a
if b == a {
a = af()
}
b = bf()
}
}
a = <-aCh
return
}
}
}
}


func main() {
func main() {
fGen := newMonoIncA_NotMonoIncB_Gen(newPowGen(2), newPowGen(3))
// square and cube generators
chSq := powCh(2)
chCu := powCh(3)

// filtered generator (in two lines)
chF := make(chan float64)
go genMonotonicIncA_NotMonotonicIncB(chF, chSq, chCu)

// collect results
for i := 0; i < 20; i++ {
for i := 0; i < 20; i++ {
<-chF
fGen()
}
}
for i := 0; i < 10; i++ {
for i := 0; i < 10; i++ {
fmt.Print(<-chF, " ")
fmt.Print(fGen(), " ")
}
}
fmt.Println("")
fmt.Println("")
}</lang>
}
</lang>
Output:
Output:
<pre>
<pre>