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