GoでメソッドチェインのMapReduceライブラリ作ろうか悩んだ
全部For文で筋力プレイしたくない
ってことで、MapReduce系のライブラリ作ろうかと悩んで下記のコードをサンプルで作った
Go Playground - The Go Programming Language
// You can edit this code! // Click here and start typing. package main import "fmt" type Map[T any] struct { value []T err bool } func NewMap[T any](v []T) *Map[T] { return &Map[T]{value: v, err: false} } func errMap[T any]() *Map[T] { return &Map[T]{nil, true} } func copyMap[T any](v []T, e bool) *Map[T] { return &Map[T]{value: v, err: e} } // var errMap Map[T] = &Map[T]{value: nil, err: true} func (s *Map[T]) Foreach(fn func(T) T) *Map[T] { if s.err { return errMap[T]() } nv := make([]T, len(s.value)) for i, v := range s.value { nv[i] = fn(v) } return copyMap(nv, false) } func (s *Map[T]) Ok() *Map[T] { if s.err { return errMap[T]() } return copyMap(s.value, false) } func (s *Map[T]) Ng() *Map[T] { if s.err { return errMap[T]() } return copyMap(s.value, true) } func (s *Map[T]) Get() ([]T, bool) { return s.value, s.err } func main() { hoge := NewMap[int]([]int{1, 2, 3, 4, 5}) result, err := hoge.Ok().Ok().Foreach(func(v int) int { return v * 2 }).Get() if err { fmt.Println("Error") } else { fmt.Printf("%v\n", result) } }
思い付きで書いたコードだけど
他のMapReduceライブラリだと、リフレクションを使うもの
コード自動生成系
があったが
リフレクションは最終手段にしたい事、interface{}になりキャストが発生
実行速度や動作不安定さが怖いので使いたくない
コードジェネレート系も、色々なからみで使いたくない
ので、ジェネリクスを使いサンプル実装してみた
まず、メソッドチェインをしたかったが、Goの基本は 値とerrのタプルを返却するものなので
タプルだとメソッドチェインが出来ないため
ジェネリクスを使い2値をもつStructを作りメソッドチェインを実現させ
Goには例外がないので、メンバ変数でErrを保持し処理をし
最後にGetメンバで、値とErr値を取得
最低限の動作はできそう
本当は遅延評価とかしたいんですけどね・・
Goで遅延評価考えたくないし、そもそもクロージャの記述がだるく、関数型に向いてないよねえ
例外処理的な事考えずに素直に関数型っぽくする方が楽かなあ・・