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 "()" }