標準愚痴出力

個人的なIT作業ログです。もしかしたら一般的に参考になることが書いているかもしれません(弱気

Go 1.23 の "iter" パッケージって冗長すぎない?(→ 関数仕様をより簡単にする試み)

( ※ 本文書のソース一式は https://github.com/hymkor/study-go-simple-rangefunc にも UP しました )

Go 1.23 で、簡単な rangefunc を書いてみたのだが、戻り値の型が無駄に複雑で過剰ラッピングに思われた。

package main

import (
    "iter"
)

type seq struct {
    values []int
}

func newSeq(v ...int) *seq {
    return &seq{values: v}
}

func (s *seq) Each() iter.Seq[int] {
    return func(callback func(int) bool) {
        for _, v := range s.values {
            if !callback(v) {
                break
            }
        }
    }
}

func main() {
    s := newSeq(1, 3, 5, 7, 9)
    for v := range s.Each() {
        println(v)
    }
}
C:> go run f.go
1
3
5
7
9

そこで "iter" に頼らず、rangefunc 関数を書いてみよう。そして、呼び出しも range s.Each() ではなく、range s.Each と少し簡単にしてみる。

package main

type seq struct {
    values []int
}

func newSeq(v ...int) *seq {
    return &seq{values: v}
}

func (s *seq) Each(callback func(int) bool) {
    for _, v := range s.values {
        if !callback(v) {
            break
        }
    }
}

func main() {
    s := newSeq(1, 3, 5, 7, 9)
    for v := range s.Each {
        println(v)
    }
}

そして、この体裁だと、"iter" を import していないので、実は Go 1.23 以前のパッケージからも呼び出すことができる

package main

// 中略

func main() {
    s := newSeq(1, 3, 5, 7, 9)
    s.Each(func(v int) bool {
        println(v)
        return true
    })
}

まとめ

rangefunc 使う場合でも、なるべく import "iter" なしで書いた方が、古い Go からも利用できてよいかもしれない。