0xf

日記だよ

pythonのジェネレータ的な書き味をgolangで

yield でシュッといけるわけではないのだが channel を返せばいいか?

func each(s, e int) <-chan int {
    r := make(chan int)
    go func() {
        defer close(r)
        for i := s; i < e; i++ {
            r <- i
        }
    }()
    return r
}

func main() {
    for i := range each(10, 20) {
        fmt.Println(i)
    }
}

range に channel を渡すと close までイテレートしてくれる、というデザインはこう使うことを想定はしているんだろう。

戻り値型として <-chan int を宣言しておくと、close操作もコンパイラに禁止される。invalid operation: cannot close receive-only channel c (variable of type <-chan int) これは良い。呼び出し側にクローズする責任がある。

チェインさせる

func each(s, e int) <-chan int {
    r := make(chan int)
    go func() {
        defer close(r)
        for i := s; i < e; i++ {
            r <- i
        }
    }()

    return r
}

func apply[T any](s <-chan T, f func(T) T) <-chan T {
    r := make(chan T)
    go func() {
        defer close(result)
        for t := range s {
            r <- f(t)
        }
    }()

    return r
}

func main() {
    for i := range apply(each(10, 20), func(i int) int { return i * 10 }) {
        fmt.Println(i)
    }
}

なるほど。ちょっと推論で補ってほしいところはあるけどタイプ数的には許容できる気がする。