Created
September 13, 2023 09:24
-
-
Save mfirhas/a97b71f34cdfa741c4a3fa3263de2d06 to your computer and use it in GitHub Desktop.
Sample code describing how to create simple iterator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// suggested solution to question on https://www.reddit.com/r/golang/comments/16g625t/cannot_compile_generic_function_that_takes_either/ | |
package main | |
import ( | |
"fmt" | |
) | |
type Iterator[T any] interface { | |
// Length return length of data on each iteration. Each iteration will reduce the length by 1. | |
Length() int | |
Iterate() T | |
} | |
type GenericSlice[T any] struct { | |
length *int | |
data *[]T | |
} | |
func NewGenericSlice[T any](a []T) GenericSlice[T] { | |
l := len(a) | |
return GenericSlice[T]{ | |
length: &l, | |
data: &a, | |
} | |
} | |
func (arr GenericSlice[T]) Length() int { | |
return len(*arr.data) | |
} | |
func (arr GenericSlice[T]) Iterate() T { | |
// fmt.Println("-----------------") | |
l := *arr.length - 1 // handle error if l reach 0, can't figure it out yet how to return (T, error), what to fill the empty/zero T? | |
*arr.length = l | |
// fmt.Println("Length: ", *arr.length) | |
// fmt.Println("Original arr.data: ", arr.data) | |
ret := (*arr.data)[0] | |
// fmt.Println("ret: ", ret) | |
newData := (*arr.data)[1:] | |
// fmt.Println("newData: ", newData) | |
newArr := make([]T, l) | |
copy(newArr, newData) | |
copy(*arr.data, newArr) | |
// fmt.Println("arr.data: ", arr.data) | |
return ret | |
} | |
type GenericMap[T any] struct { | |
length *int | |
data *map[any]T | |
} | |
func NewGenericMap[V any](m map[any]V) GenericMap[V] { | |
l := len(m) | |
return GenericMap[V]{ | |
length: &l, | |
data: &m, | |
} | |
} | |
func (m GenericMap[T]) Length() int { | |
return len(*m.data) | |
} | |
func (m GenericMap[T]) Iterate() T { | |
var currentV T | |
// fmt.Println("current map: ", m.data) | |
for k, v := range *m.data { | |
currentV = v | |
delete(*m.data, k) | |
// fmt.Println("current map after delete: ", m.data) | |
break | |
} | |
return currentV | |
} | |
func Make[E any, T Iterator[E]](t T) []E { | |
length := t.Length() | |
result := make([]E, length) | |
for i := 0; i < length; i++ { | |
result[i] = t.Iterate() | |
} | |
return result | |
} | |
func main() { | |
// []int | |
ints := []int{1, 2, 3} | |
fmt.Println("[]int before", ints) | |
iterableInts := NewGenericSlice(ints) | |
fmt.Println("[]int after: ", Make(iterableInts)) | |
// map | |
maps := make(map[any]int) | |
maps[1] = 1 | |
maps[2] = 2 | |
maps[3] = 3 | |
fmt.Println("map[any]int before", maps) | |
iterableMap := NewGenericMap(maps) | |
fmt.Println("map[any]int after: ", Make(iterableMap)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment