Skip to content

Instantly share code, notes, and snippets.

@erwinv
Last active March 21, 2022 18:03
Show Gist options
  • Save erwinv/29d3cfe80c3ce4d23612360de3dc2c5f to your computer and use it in GitHub Desktop.
Save erwinv/29d3cfe80c3ce4d23612360de3dc2c5f to your computer and use it in GitHub Desktop.
package main
import "fmt"
// List represents a singly-linked list that holds
// values of any type.
type List[T any] struct {
next *List[T]
val T
}
func From[T any](vs []T) (l List[T]) {
l = List[T]{}
curr := &l
for i, v := range vs {
curr.val = v
if i + 1 < len(vs) {
curr.next = &List[T]{}
curr = curr.next
}
}
return
}
func (l *List[T]) Size() (size int) {
for size = 1; l.next != nil; size++ {
l = l.next
}
return
}
func (l *List[T]) To() (vs []T) {
vs = make([]T, l.Size())
for i := range vs {
vs[i] = l.val
l = l.next
}
return
}
func (l *List[T]) For(it func(v T)) {
it(l.val)
if l.next != nil {
l.next.For(it)
}
}
// not supported, methods cannot be generic, what a shame
// func (l *List[T]) Map[U](mapper func(v T) U) (r List[U])
func (l *List[T]) Map(mapper func(v T) T) (r List[T]) {
r = List[T]{}
curr := &r
slice := l.To()
for i, v := range slice {
curr.val = mapper(v)
if i + 1 < len(slice) {
curr.next = &List[T]{}
curr = curr.next
}
}
return
}
func (l *List[T]) Push(v T) {
newlast := List[T]{val: v}
last := l
for ; last.next != nil; last = last.next {}
last.next = &newlast
}
func (l *List[T]) Append(r *List[T]) {
last := l
for ; last.next != nil; last = last.next {}
last.next = r
}
func (l *List[T]) FoldLeft(combiner func(T, T) T) (acc T) {
for i, v := range l.To() {
if i == 0 {
acc = v
} else {
acc = combiner(acc, v)
}
}
return
}
func main() {
list1 := From([]int{1,2,3})
list2 := From([]int{5,6,7})
fmt.Println("list1:", list1.To())
fmt.Println("list2:", list2.To())
list1.Push(4)
list2.Push(8)
fmt.Println("list1 + [4]:", list1.To())
fmt.Println("list2 + [8]:", list2.To())
list1.Append(&list2)
fmt.Println("list1 ++ list2:", list1.To())
fmt.Println("sum:", list1.FoldLeft(add[int]))
squares := list1.Map(square)
fmt.Println("squares:", squares.To())
fmt.Println("sum of squares:", squares.FoldLeft(add[int]))
}
type Number interface {
int | float64
}
func add[T Number](x T, y T) T {
return x + y
}
func multiply[T Number](x T, y T) T {
return x * y
}
func square(x int) int {
return multiply(x, x)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment