Upgrade to Pro — share decks privately, control downloads, hide ads and more …

まずはイテレータ(range over func)の仕様を学ぼう

まずはイテレータ(range over func)の仕様を学ぼう

tenntenn - Takuya Ueda

September 24, 2024
Tweet

More Decks by tenntenn - Takuya Ueda

Other Decks in Technology

Transcript

  1. The Go gopher was designed by Renée French. The gopher

    stickers was made by Takuya Ueda. Licensed under the Creative Commons 3.0 Attributions license. まずはイテレータ (range over func)の 仕様を学ぼう 2024/09/24 Goのイテレータ深堀りNight https://tenn.in/iternight 1
  2. UEDA Takuya / tenntenn 上田拓 也 newmo株式会社 / ソフトウェアエンジニア 2013年よりGo

    Conferenceの運営を行う。 
 2016年、メルカリグループに入社、Goコミュニティへの貢献や採用・社内教育などに従事。 
 2021年、一般社団法人Gophers Japan設立、代表理事に就任。Google Developers Expert (GDE)に選出。 
 2022年、株式会社ナレッジワーク入社。ソフトウェアエンジニアおよびGoエンジニアのイネーブルメントに従事。 
 2024年、newmo株式会社入社。ソフトウェアエンジニアとしてプロダクト開発に従事。 
 略歴
  3. イテレータの導入経緯 Go1.18 Go1.21 Go1.23 ジェネリクス (型パラメータ) の導入 slices, maps パッケージの導入

    イテレータ (range over func) の導入 stdは変更最小限 maps.Keysは 導入されず stdは変更最小限 ※ std: 標準ライブラリ ジェネリクスの導入の議論の中でイテレータという概念が生じ、別の議論へと発展した
  4. 型パラメータのおさらい パラメータ 関数パラメータ 型パラメータ 外から変更できるもの func F(n int) { fmt.Println(n)

    } F(10) func F() { fmt.Println(10) } func G[T any](v T) { fmt.Println(v) } G[int](10) // G(10) func G(v int) { fmt.Println(v) } 仮引数 実引数 な し あ り 指 定 型パラメータ 型引数
  5. イテレータ( range over func) 1 2 3 seq0 := func(yield

    func() bool) {} for range seq0 {} seq1 := func(yield func(X) bool) {} for x := range seq1 {} seq2 := func(yield func(X, Y) bool) {} for x, y := range seq2 {} for range文に関数が指定できるようになった
  6. range over funcと他のrange over 対象 こ れ ま で 関

    数 振る舞い [N]E, *[N]E, []E, map[K]V, string, chan E, <-chan E, N func(func() bool) func(func(X) bool) func(func(X, Y) bool) 型ごとに決められている 例:先頭から順に 関数によって実装する 例:後方から、深さ優先探索 イテレーションの仕方が自由になった
  7. 重要な3つの仕様 1 for range文に指定した関数が 1度だけ実行される 2 yield関数を呼ぶと for文のボディに処理が移る 3 for

    range文が途中で終了すると yield関数がfalseを返す for range func call for range func yield for range func false break return
  8. 例:アルファベット列の生成 func Alphabet(yield func(rune) bool) { for c := 'A';

    c <= 'Z'; c++ { // 'A', 'B', 'C', … if !yield(c) { return } } } func usage() { // ABC for c := range Alphabet { fmt.Printf("%c", c) if c == 'C' { break } } }
  9. 標準ライブラリの変更点 1 2 type Seq[V any] func(yield func(V) bool) type

    Seq2[K, V any] func(yield func(K, V) bool) iterパッケージと iter.Seq型とiter.Seq2型が導入された ※ iter.Pull関数とiter.Pull2関数についてはeihighさんにお任せします!
  10. 例:マップ関数 func Map[X, Y any](seq iter.Seq[X], f func(X) Y) iter.Seq[Y]

    { return func(yield func(Y) bool) { for x := range seq { if !yield(f(x)) { break } } } } func usage() { seq := Map(slices.Values([]int{10, 20}), func(x int) string { return fmt.Sprintf("0x%x", x) }) // 0xa // 0x14 for v := range seq { fmt.Println(v) } }