mal-go/list/list.go
ajet db1bd5f322
All checks were successful
Go / test (push) Successful in 10s
bring back empty() vs new(val)
2025-11-04 13:03:00 -10:00

124 lines
1.7 KiB
Go

package list
import (
"fmt"
"strings"
)
type IList interface {
Conj(data any) IList
First() any
Rest() IList
String() string
IsEmpty() bool
}
type EmptyList struct{}
type List struct {
Value any
next IList
}
func Empty() IList {
return new(EmptyList)
}
var emptyList = Empty()
func New(val any) *List {
this := new(List)
this.Value = val
this.next = emptyList
return this
}
func (this *List) Conj(val any) IList {
new_head := New(val)
new_head.next = this
return new_head
}
func (this *EmptyList) Conj(val any) IList {
return Conj(nil, val)
}
func Conj(this IList, val any) IList {
if this == nil {
return New(val)
} else {
return this.Conj(val)
}
}
func Rest(this IList) IList {
if this == nil {
return emptyList
}
return this.Rest()
}
func (this *List) Rest() IList {
if this == nil {
return emptyList
}
return this.next
}
func (this *EmptyList) Rest() IList {
return emptyList
}
func First(this *List) any {
if this == nil {
return nil
}
return this.Value
}
func (this *List) First() any {
return First(this)
}
func (this *EmptyList) First() any {
return nil
}
func IsEmpty(this IList) bool {
return this == nil || this.IsEmpty()
}
func (this *List) IsEmpty() bool {
return false
}
func (this *EmptyList) IsEmpty() bool {
return true
}
func String(this *List) string {
if IsEmpty(this) {
return "()"
}
var sb strings.Builder
sb.WriteRune('(')
// Iterate and print elements
var e IList
for e = this; !IsEmpty(e); e = Rest(e) {
sb.WriteString(fmt.Sprint(e.First()))
sb.WriteRune(' ')
}
return sb.String()[:sb.Len()-1] + ")"
}
func (this *List) String() string {
return String(this)
}
func (this *EmptyList) String() string {
return "()"
}