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.

Reply via email to