Skip to content

Instantly share code, notes, and snippets.

@mfirhas
Created September 13, 2023 09:24
Show Gist options
  • Save mfirhas/a97b71f34cdfa741c4a3fa3263de2d06 to your computer and use it in GitHub Desktop.
Save mfirhas/a97b71f34cdfa741c4a3fa3263de2d06 to your computer and use it in GitHub Desktop.
Sample code describing how to create simple iterator
// 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