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