Generator/Exponential: Difference between revisions
Content added Content deleted
(→{{header|Go}}: added channel version) |
|||
Line 687: | Line 687: | ||
fmt.Print(fGen(), " ") |
fmt.Print(fGen(), " ") |
||
} |
} |
||
fmt.Println( |
fmt.Println() |
||
}</lang> |
}</lang> |
||
Output: |
Output: |
||
Line 693: | Line 693: | ||
529 576 625 676 784 841 900 961 1024 1089 |
529 576 625 676 784 841 900 961 1024 1089 |
||
</pre> |
</pre> |
||
Alternatively, generators can be implemented in Go with goroutines and channels. There are tradeoffs however, and often one technique is a significantly better choice. |
|||
Goroutines can run concurrently, but there is overhead associated with thread scheduling and channel communication. Flow control is also different. A generator implemented as a closure is a function with a single entry point fixed at the beginning. On repeated calls, execution always starts over at the beginning and ends when a value is returned. A generator implemented as a goroutine, on the other hand, "returns" a value by sending it on a channel, and then the goroutine continues execution from that point. This allows more flexibility in structuring code. |
|||
<lang go>package main |
|||
import ( |
|||
"fmt" |
|||
"math" |
|||
) |
|||
func newPowGen(e float64) chan float64 { |
|||
ch := make(chan float64) |
|||
go func() { |
|||
for i := 0.; ; i++ { |
|||
ch <- math.Pow(i, e) |
|||
} |
|||
}() |
|||
return ch |
|||
} |
|||
// given two input channels, a and b, both known to return monotonically |
|||
// increasing values, supply on channel c values of a not returned by b. |
|||
func newMonoIncA_NotMonoIncB_Gen(a, b chan float64) chan float64 { |
|||
ch := make(chan float64) |
|||
go func() { |
|||
for va, vb := <-a, <-b; ; { |
|||
switch { |
|||
case va < vb: |
|||
ch <- va |
|||
fallthrough |
|||
case va == vb: |
|||
va = <-a |
|||
default: |
|||
vb = <-b |
|||
} |
|||
} |
|||
}() |
|||
return ch |
|||
} |
|||
func main() { |
|||
ch := newMonoIncA_NotMonoIncB_Gen(newPowGen(2), newPowGen(3)) |
|||
for i := 0; i < 20; i++ { |
|||
<-ch |
|||
} |
|||
for i := 0; i < 10; i++ { |
|||
fmt.Print(<-ch, " ") |
|||
} |
|||
fmt.Println() |
|||
}</lang> |
|||
=={{header|Haskell}}== |
=={{header|Haskell}}== |