start the tower of abstractions
Some checks failed
Go / test (push) Failing after 28s

This commit is contained in:
Adam Jeniski 2025-11-04 12:25:23 -10:00
parent d3997bfb53
commit 4e1cbce3a7
4 changed files with 63 additions and 36 deletions

View File

@ -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))
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)
}

View File

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

View File

@ -43,7 +43,7 @@ func TestReadListElem(t *testing.T) {
func TestReadList(t *testing.T) {
input := "(1 2 3)"
l, err, pos := readList(input, 0, "user")
assert.Equal(t, list.New(3).Conj(2).Conj(1), l, "should read list")
assert.Equal(t, list.New().Conj(3).Conj(2).Conj(1), l, "should read list")
assert.Equal(t, nil, err, "should read without error")
assert.Equal(t, len(input), pos, "should read the whole string")
}

View File

@ -51,15 +51,14 @@ func (this *Vector) String() string {
return String(this)
}
func ToList(this *Vector) *list.List {
var l *list.List
l = nil
func ToList(this *Vector) list.IList {
l := list.New()
for i := len(this._slice) - 1; i >= 0; i-- {
l = list.Conj(l, this._slice[i])
}
return l
}
func (this *Vector) ToList() *list.List {
func (this *Vector) ToList() list.IList {
return ToList(this)
}