Looking at how C++ has chosen to provide it's users with generators served as a bit of a wake-up call for me on how we implement them in Go. We write them backwards:
```go func getPositiveOdds(numbers []int) <-chan int { channel := make(chan int) go func () { defer close(channel) for _, value := range numbers { if value > 0 && (value & 1) == 1 { channel <- value } } }() return channel } ``` What does this function do? It allocates something and then it forks something off in the background. And then - surprise - there's a return at the end? This pattern/idiom is very un-golike in that it's an eyesore, and one of the hardest things I've found to teach people new to trying to read go code. I've toyed with a few alternatives, but I'm having a hard time finding something I think everyone would like. Pattern the first; 'go return` which flips the idiom with syntactic sugar. 'go return' returns the function and continues the remainder of it in a go func() { ... } ```go func getPositiveOdds(numbers []int) <-chan int { channel := make(chan int) go return channel defer close(channel) for _, value := range numbers { if value > 0 && (value & 1) == 1 { channel <- value } } } ``` The second more closely binds to the channel-generator pattern by extending make(chan) to take a 'go func' parameter: ```go func getPositiveOdds(numbers []int) <-chan int { generator := make(chan int, go func (channel chan int) { defer close(channel) for _, value := range numbers { if value > 0 && (value & 1) == 1 { channel <- value } } }) return generator } ``` I was tempted by the notion of having this auto-defer-close the channel, but I think retaining the explicit close is generally better and more teachable. Where it might be tenable would be using syntactic sugar to perhaps better promote the notion of generators toward 1st class citizens: ```go // 'generator' is syntactic sugar, and instead of a return type you provide // the make statement to create the required channel type. generator getPositiveOdds(numbers []int) make(chan int, 1) { // The variable 'yield' is automatically defined as the channel created for _, value := range numbers { if value > 0 && (value & 1) == 1 { yield <- value } } } ``` which is roughly equivalent to: ```golang func getPositiveOdds(numbers []int]) <-chan int { generator := func (yield chan int) { numbers := numbers for _, value := range numbers { if value > 0 && (value & 1) == 1 { yield <- value } } } channel := make(chan int, 1) go func () { defer close(channel) generator(channel) }() return channel } ``` `gen` instead of `generator` might be ok, I just wanted to be unambiguous. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/5aa92ac7-1c9b-48af-8389-a6870563b831n%40googlegroups.com.