0xf

日記だよ

golangでメソッドには型パラメータは付与できないけどレシーバには付与できる

pythonのジェネレータ的な書き味をgolangで - 0xfを書いていて気がついたのだけど、

なんか勘違いしていて、メソッドは型パラメータ持てないよといったとき、レシーバも同様かと思い込んでいた。

type ReadOnlyChannel[T any] <-chan T

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

    return r
}

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

    return r
}

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

こういうことはできる。

関数の配列などもレシーバにできるので

関数の連続適用もできる。

type F[T any] []func(T) T

func (funcs F[T]) chain(a T) T {
    for _, f := range funcs {
        a = f(a)
    }
    return a
}

func main() {
    funcs := F[int]([]func(int) int{
        func(a int) int { return a * 2 },
        func(a int) int { return a + 1 },
        func(a int) int { return a * 100 }})
    result := funcs.chain(3)
    println(result)
}

以下が冗長なので、

   funcs := F[int]([]func(int) int{
        func(a int) int { return a * 2 },
        func(a int) int { return a + 1 },
        func(a int) int { return a * 100 }})

こうする。

   funcs := F[int]{
        func(a int) int { return a * 2 },
        func(a int) int { return a + 1 },
        func(a int) int { return a * 100 }}

よし。