Go/メソッドチェイン
表示
< Go
メソッドチェイン
[編集]Goのメソッドは、メソッドチェイン(method chaining)が可能です。
- メソッドチェイン
package main import "fmt" // Student 構造体を定義 type Student struct { name string age int } // PrintName メソッドを定義(ポインタレシーバー) func (s *Student) PrintName() *Student { fmt.Printf("Name: %v\n", s.name) return s // メソッドチェインのため、ポインタを返す } // PrintAge メソッドを定義(ポインタレシーバー) func (s *Student) PrintAge() *Student { fmt.Printf("Age: %v\n", s.age) return s // メソッドチェインのため、ポインタを返す } func main() { // 学生のリストを定義 students := [...]Student{ {name: "joe", age: 17}, {name: "tom", age: 18}, {name: "alice", age: 17}, } // 学生ごとにPrintNameとPrintAgeを呼び出し // 配列要素を直接ループ for _, student := range students { student.PrintName().PrintAge() // メソッドチェイン } }
- 結果
Name: joe Age: 17 Name: tom Age: 18 Name: alice Age: 17
遅延評価を使用するシーケンス
[編集]- lazy.go
package main import ( "fmt" "strings" ) // Seq は遅延評価を使用するシーケンスを表す型 type Seq[T any] func(yield func(T) bool) // 新しいSeqを作成する関数 func NewSeq[T any](elements ...T) Seq[T] { return func(yield func(T) bool) { for _, el := range elements { if !yield(el) { break } } } } // Push はSeqの末尾に要素を追加 func (seq Seq[T]) Push(element T) Seq[T] { return func(yield func(T) bool) { seq(func(v T) bool { if !yield(v) { return false } return true }) } } // Pop はSeqの末尾から要素を削除(シミュレート) func (seq Seq[T]) Pop() Seq[T] { return func(yield func(T) bool) { // Pop動作を実装するためにはSeqを一度リストに変換して操作する必要あり // ここでは簡略化してます。 seq(yield) // 戻り値のシミュレーション } } // Map はSeqの各要素に対して関数を適用 func (seq Seq[T]) Map(fn func(T) T) Seq[T] { return func(yield func(T) bool) { seq(func(v T) bool { return yield(fn(v)) }) } } // Filter はSeqの各要素を条件でフィルタリング func (seq Seq[T]) Filter(fn func(T) bool) Seq[T] { return func(yield func(T) bool) { seq(func(v T) bool { if fn(v) { return yield(v) } return true }) } } // Reduce はSeqの各要素を累積的に処理 func (seq Seq[T]) Reduce(fn func(T, T) T, initial T) T { accumulator := initial seq(func(v T) bool { accumulator = fn(accumulator, v) return true }) return accumulator } // Concat は二つのSeqを結合 func (seq1 Seq[T]) Concat(seq2 Seq[T]) Seq[T] { return func(yield func(T) bool) { seq1(yield) seq2(yield) } } // ForEach はSeqの各要素に対して指定された関数を実行 func (seq Seq[T]) ForEach(fn func(T)) { seq(func(v T) bool { fn(v) return true }) } // ToSlice はSeqをスライスに変換 func ToSlice[T any](seq Seq[T]) []T { var result []T seq(func(v T) bool { result = append(result, v) return true }) return result } // Stringerインターフェースを実装 func (seq Seq[T]) String() string { slice := []string{} seq(func(v T) bool { slice = append(slice, fmt.Sprintf("%v", any(v))) return true }) return fmt.Sprintf("{%s}", strings.Join(slice, ", ")) } // GoStringerインターフェースを実装 func (seq Seq[T]) GoString() string { slice := []string{} seq(func(v T) bool { slice = append(slice, fmt.Sprintf("%v", any(v))) return true }) return fmt.Sprintf("NewSeq(%s)", strings.Join(slice, ", ")) } func main() { // Seqを作成 seq1 := NewSeq(1, 2, 3) seq2 := NewSeq(4, 5) // Seqを結合 seq3 := seq1.Concat(seq2) // 結果をToSliceで表示 fmt.Printf("Concatenated Seq: %s(%#v)\n", seq3, seq3) // {1, 2, 3, 4, 5}(NewSeq(1, 2, 3, 4, 5)) // Mapを使って各要素を2倍にする doubledSeq := seq3.Map(func(x int) int { return x * 2 }) fmt.Println("Doubled Seq:", doubledSeq) // {2, 4, 6, 8, 10} // Filterを使って偶数を抽出 evenSeq := seq3.Filter(func(x int) bool { return x%2 == 0 }) fmt.Println("Even Seq:", evenSeq) // {2, 4} // ForEachを使って各要素を表示 seq3.ForEach(func(x int) { fmt.Println("ForEach element:", x) }) // Reduceを使って合計を計算 sum := seq3.Reduce(func(acc, x int) int { return acc + x }, 0) fmt.Println("Sum:", sum) // 15 }