+50
-26
@@ -5,57 +5,71 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IList interface {
|
||||
Conj(data any) IList
|
||||
First() any
|
||||
Rest() IList
|
||||
String() string
|
||||
}
|
||||
|
||||
type EmptyList struct{}
|
||||
|
||||
type List struct {
|
||||
Value any
|
||||
next *List
|
||||
next IList
|
||||
}
|
||||
|
||||
func Empty() *EmptyList {
|
||||
func New() IList {
|
||||
return new(EmptyList)
|
||||
}
|
||||
|
||||
func New(val any) *List {
|
||||
return new(List).Init(val)
|
||||
}
|
||||
|
||||
func (this *List) Init(val any) *List {
|
||||
return Init(this, val)
|
||||
}
|
||||
|
||||
func Init(this *List, val any) *List {
|
||||
func single(val any) *List {
|
||||
this := new(List)
|
||||
this.Value = val
|
||||
this.next = nil
|
||||
return this
|
||||
}
|
||||
|
||||
func (this *List) Conj(val any) *List {
|
||||
return Conj(this, val)
|
||||
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) *List {
|
||||
func (this *EmptyList) Conj(val any) IList {
|
||||
return Conj(nil, val)
|
||||
}
|
||||
|
||||
func Conj(this *List, val any) *List {
|
||||
func Conj(this IList, val any) IList {
|
||||
var l IList
|
||||
if this == nil {
|
||||
return New(val)
|
||||
l = single(val)
|
||||
} else {
|
||||
l = this
|
||||
}
|
||||
new_head := New(val)
|
||||
new_head.next = this
|
||||
return new_head
|
||||
return l.Conj(val)
|
||||
}
|
||||
|
||||
func Rest(this *List) *List {
|
||||
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 *List) Rest() *List {
|
||||
return Rest(this)
|
||||
func (this *EmptyList) Rest() IList {
|
||||
return nil
|
||||
}
|
||||
|
||||
func First(this *List) any {
|
||||
@@ -73,7 +87,7 @@ func (this *EmptyList) First() any {
|
||||
return First(nil)
|
||||
}
|
||||
|
||||
func IsEmpty(this *List) bool {
|
||||
func IsEmpty(this IList) bool {
|
||||
return this == nil
|
||||
}
|
||||
|
||||
@@ -92,9 +106,15 @@ func String(this *List) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteRune('(')
|
||||
// Iterate and print elements
|
||||
for e := this; e != nil; e = Rest(e) {
|
||||
sb.WriteString(fmt.Sprint(e.Value))
|
||||
sb.WriteRune(' ')
|
||||
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] + ")"
|
||||
}
|
||||
@@ -102,3 +122,7 @@ func String(this *List) string {
|
||||
func (this *List) String() string {
|
||||
return String(this)
|
||||
}
|
||||
|
||||
func (this *EmptyList) String() string {
|
||||
return String(nil)
|
||||
}
|
||||
|
||||
+9
-5
@@ -6,20 +6,24 @@ import (
|
||||
)
|
||||
|
||||
func TestReadConj(t *testing.T) {
|
||||
l := Empty().Conj(5).Conj(6).Conj(7)
|
||||
l := New().Conj(5).Conj(6).Conj(7)
|
||||
assert.Equal(t, "(7 6 5)", l.String(), "should insert at head")
|
||||
l = Conj(New(), 4)
|
||||
assert.Equal(t, "(4 5)", l.String(), "should insert at head")
|
||||
}
|
||||
|
||||
func TestReadFirst(t *testing.T) {
|
||||
l := Empty().Conj(5).Conj(6).Conj(7)
|
||||
l := New().Conj(5).Conj(6).Conj(7)
|
||||
assert.Equal(t, 7, l.First(), "should return first element")
|
||||
assert.Equal(t, nil, Empty().First(), "should return nil")
|
||||
assert.Equal(t, 5, New(5).First(), "should get first from New")
|
||||
assert.Equal(t, nil, New().First(), "should return nil")
|
||||
}
|
||||
|
||||
func TestReadRest(t *testing.T) {
|
||||
l := Empty().Conj(5).Conj(6).Conj(7)
|
||||
l := New().Conj(5).Conj(6).Conj(7)
|
||||
assert.Equal(t, "(6 5)", l.Rest().String(), "should return rest sublist")
|
||||
assert.Equal(t, "(5)", l.Rest().Rest().String(), "should return rest sublist")
|
||||
assert.Equal(t, "()", l.Rest().Rest().Rest().String(), "should return rest sublist")
|
||||
var nilPtr *List = nil
|
||||
assert.Equal(t, nilPtr, New().Rest(), "should return rest sublist")
|
||||
assert.Equal(t, nilPtr, Rest(New().Rest()), "should return rest sublist")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user