Any values can be used as elements in the lists. Thus you can use your own structs etc. as elements, you don't need to do anything special to include them.
The functions all use interface{} and return interface{} values, this makes it just easier seeing that we can make use of any types.
Currently there is no scanner to convert a string to a list and also no evaluator.
A basic example of what can be done is:
package main
import (
"fmt"
lsp "github.com/hduplooy/glisp"
)
func main() {
lst1 := lsp.List(1, 2, 3, "Hansel", "Gretel", lsp.List("+", "a", "b"))
lst2 := lsp.List("diff", lsp.List("cos", lsp.List("^", "x", 2)), "x")
lst3 := lsp.Append(lst1, lst2)
lst4 := lsp.Clone(lst1)
fmt.Println("lst1=" + lsp.ToString(lst1))
fmt.Println("lst2=" + lsp.ToString(lst2))
fmt.Println("lst3 Append(lst1,lst2)=" + lsp.ToString(lst3))
fmt.Println("lst4 Clone(lst1)=" + lsp.ToString(lst4))
fmt.Println("Nth(lst1,3)=" + lsp.ToString(lsp.Nth(lst1, 3)))
fmt.Println("NthCdr(lst1,3)=" + lsp.ToString(lsp.NthCdr(lst1, 3)))
fmt.Println("Head(lst3,4)=" + lsp.ToString(lsp.Head(lst3, 4)))
fmt.Printf("Length(lst3)=%d\n", lsp.Length(lst3))
fmt.Println("Tail(lst3,4)=" + lsp.ToString(lsp.Tail(lst3, 4)))
lst5 := lsp.Map(func(vals []interface{}) interface{} {
return lsp.List(vals...)
}, lst1, lsp.Reverse(lst1))
fmt.Println("lst5 Map=" + lsp.ToString(lst5))
fmt.Println("Cons(\"a\",2)=" + lsp.ToString(lsp.Cons("a", 2)))
fmt.Println("MakeList(5,\"*\")=" + lsp.ToString(lsp.MakeList(5, "*")))
fmt.Println("LastPair(lst1)=" + lsp.ToString(lsp.LastPair(lst1)))
fmt.Println("Sublist(lst3,5,3)=" + lsp.ToString(lsp.Sublist(lst3, 5, 3)))
lsp.SetNth(lst1, 2, "XXX")
fmt.Println("SetNth(lst1,2,\"XXX\")=" + lsp.ToString(lst1))
lst6 := lsp.Clone(lst3)
lsp.SetNthCdr(lst6, 4, lsp.List("a", "b", "c"))
fmt.Println("SetNthCdr(Clone(lst3),4,List(a,b,c))=" + lsp.ToString(lst6))
fmt.Println("Filter=" + lsp.ToString(lsp.Filter(func(val interface{}) bool {
return lsp.IsNumber(val)
}, lst1)))
fmt.Println("Delete=" + lsp.ToString(lsp.Delete(func(val interface{}) bool {
return lsp.IsNumber(val)
}, lst1)))
fmt.Println("Member=" + lsp.ToString(lsp.Member(func(val interface{}) bool {
return lsp.IsString(val) && val.(string) == "Hansel"
}, lst3)))
fmt.Println("Fold=" + lsp.ToString(lsp.Fold(func(lst1, lst2 interface{}) interface{} {
if lsp.IsInt(lst1) {
return lst1.(int) + lst2.(int)
}
return lst2
}, lst3, 0)))
lst7 := lsp.List(lsp.Cons("john", 16), lsp.Cons("mary", 14), lsp.Cons("bob", 15), lsp.Cons("sarah", 13))
fmt.Println("lst7=" + lsp.ToString(lst7))
fmt.Println("Assoc=" + lsp.ToString(lsp.Assoc(func(val1 interface{}) bool {
return lsp.IsString(val1) && val1.(string) == "mary"
}, lst7)))
}
This will return the following:
lst1=(1 2 3 Hansel Gretel (+ a b))
lst2=(diff (cos (^ x 2)) x)
lst3 Append(lst1,lst2)=(1 2 3 Hansel Gretel (+ a b) diff (cos (^ x 2)) x)
lst4 Clone(lst1)=(1 2 3 Hansel Gretel (+ a b))
Nth(lst1,3)=Hansel
NthCdr(lst1,3)=(Hansel Gretel (+ a b))
Head(lst3,4)=(1 2 3 Hansel)
Length(lst3)=9
Tail(lst3,4)=((+ a b) diff (cos (^ x 2)) x)
lst5 Map=((1 (+ a b)) (2 Gretel) (3 Hansel) (Hansel 3) (Gretel 2) ((+ a b) 1))
Cons("a",2)=(a . 2)
MakeList(5,"*")=(* * * * *)
LastPair(lst1)=((+ a b))
Sublist(lst3,5,3)=((+ a b) diff (cos (^ x 2)))
SetNth(lst1,2,"XXX")=(1 2 XXX Hansel Gretel (+ a b))
SetNthCdr(Clone(lst3),4,List(a,b,c))=(1 2 3 Hansel Gretel a b c)
Filter=(1 2)
Delete=(XXX Hansel Gretel (+ a b))
Member=(Hansel Gretel (+ a b) diff (cos (^ x 2)) x)
Fold=6
lst7=((john . 16) (mary . 14) (bob . 15) (sarah . 13))
Assoc=(mary . 14)
IsNode checks if val is a Node
IsNil is a helper function to check if val is nil
IsString is a helper function to check if val is a string
IsInt is a help function to check if val is an int
IsInt8 is a help function to check if val is an int8
IsInt16 is a help function to check if val is an int16
IsInt32 is a help function to check if val is an int32
IsInt64 is a help function to check if val is an int64
IsUint is a help function to check if val is an uint
IsUint8 is a help function to check if val is an uint8
IsUint16 is a help function to check if val is an uint16
IsUint32 is a help function to check if val is an uint32
IsUint64 is a help function to check if val is an uint64
IsByte is a help function to check if val is a byte
IsFloat64 is a help function to check if val is a float64
IsFloat32 is a help function to check if val is a float32
IsComplex64 is a help function to check if val is a complex64
IsComplex128 is a help function to check if val is a complex128
IsNumber is a help function to check if val is any of the numeric types
IsBool is a help function to check if val is a bool
MakeList will generate a list of n elements with each element being val.
For example glisp.MakeList(5,"a") will return ("a" "a" "a" "a" "a")
Cons just creates a new node with Car=val1 and Cdr=val2
For example:
- glisp.Cons(4,nil) will return (4)
- glisp.Cons("a",4) will return ("a" . 4)
List creates a list from the slice of vals
For example:
- glisp.List(1,2,3,4) will return (1 2 3 4)
- glisp.List("+",1,glisp.List("-","a",10)) will return ("+" 1 ("-" "a" 10))
Append will concatenate lists together and return a new list.
For example:
- glisp.Append(glisp.List("a","b","c"),glisp.List(1,2,3)) returns (("a" "b" "c") (1 2 3))
CloneNode create a new Node with the same Car and Cdr values
Clone will create a new list at the top level for deep cloning look at DeepClone.
When a cloned list is changed the original will not be changed
DeepClone will create a new list, but for each value that is also a list it will be also cloned.
When anything in the deep cloned list structure is changed the original is not changed
Car returns the Car value of a Node else nil if it is not a Node.
For example:
lst1 := glisp.List("a","b","c")
lst2 := glisp.Car(lst1) // Returns "a"
Cdr returns the Cdr value of a Node else nil if it is not a Node.
For example:
lst1 := glisp.List("a","b","c")
lst2 := glisp.Cdr(lst1) // Returns ("b" "c")
Nth will return the n'th value in the list else nil.
For example:
glisp.Nth(glisp.List("a","b","c","d"),2) // will return "c"
NthCdr will return the n'th applcation of Cdr on the list.
For example:
glisp.NthCdr(glisp.List("a","b","c","d"),2) // will return ("d")
Head returns the first n elements of a list else nil if it is not a node or too short.
For example:
glisp.Head(glisp.List("a","b","c","d"),2) // will return ("a" "b")
Tail will return the last n elements in the list.
For example:
glisp.Tail(glisp.List("a","b","c","d"),2) // will return ("c" "d")
LastPair returns the very last Node in the list.
For example:
- glisp.LastPair(glisp.List("a","b","c","d")) will return ("d")
- glisp.LastPair(glisp.List("a","b","c",glisp.Cons("d","e"))) will return ("d". "e")
Sublist returns part of the list from the start position for items number of elements.
For example:
glisp.Sublist(glisp.List("a","b","c","d"),1,2) // will return ("b" "c")
Length returns the number of elements in the list.
For example:
glisp.Length(glisp.List("a","b","c","d")) will return 4
Reverse returns a list in reverse order.
For example:
glisp.Reverse(glisp.List("a","b","c","d")) // will return ("d" "c" "b" "a")
ToSlice will convert a list to a slice.
For example:
glisp.ToSlice(glisp.List("a","b","c","d")) //will return []interface{}{"a","b","c","d"}
ToString will convert the list to a string representation of the list.
For example:
glisp.ToString(glisp.List("+",1,glisp.List("-","a",10))) will return "(+ 1 (- a 10))"
SetCar will set the Car element if it is a Node.
For example:
lst1 := glisp.Cons("a","b")
glisp.SetCar(lst1,"c")
fmt.Println(glisp.ToString(lst1)) // Will produce "(c b)"
SetCdr will set the Cdr element if it is a Node For example:
lst1 := glisp.Cons("a","b")
glisp.SetCdr(lst1,"c")
fmt.Println(glisp.ToString(lst1)) // Will produce "(a c)"
SetNth will set the Car of n'th value of the list to val For example:
lst1 := glisp.List("a","b","c","d","e")
glisp.SetNth(lst1,2,"z")
fmt.Println(glisp.ToString(lst1)) // Will produce "(a b z d e)"
SetNthCdr will set the Cdr of n'th value of the list to val For example:
lst1 := glisp.List("a","b","c","d","e")
glisp.SetNthCdr(lst1,2,glisp.List("x","y","z"))
fmt.Println(glisp.ToString(lst1)) // Will produce "(a b c x y z)"
Map will apply the function f to elements of lists provided and return a new list.
For example:
f := func{vals []interface{}) interface{} {
if len(vals)>=2 {
return glisp.Cons(vals[0],vals[1])
}
return nil
}
lst1 := glisp.Map(f,glisp.List("a","b","c"),glisp.List(1,2,3)) // This returns (("a" . 1) ("b" . 2) ("c" . 3))
ForEach will apply the function f to elements of lists provided (nothing is returned).
For example:
f := func{vals []interface{}) {
if len(vals)>=2 {
fmt.Printf("%v - %v\n",vals[0],vals[1])
}
}
glisp.ForEach(f,glisp.List("a","b","c"),glisp.List(1,2,3))
// This will output:
// a - 1
// b - 2
// c - 3
Filter will use function f to select which elements to return in a new list. For example:
f := func{val interface{}) bool {
return glisp.IsNumber(val)
}
lst1 := glisp.Filter(f,glisp.List("a",5,"b","c",1,"z",2,3)) // This returns (5 1 2 3)
Delete will use function f to select which elements not to return in a new list. For example:
f := func{val interface{}) bool {
return glisp.IsNumber(val)
}
lst1 := glisp.Delete(f,glisp.List("a",5,"b","c",1,"z",2,3)) // This returns ("a" "b" "c" "z")
Member will use f to return the first Node for which f returns true on its Car.
For example:
f := func(val interface{}) bool {
return glisp.IsString(val) && val.(string) == "c"
}
lst1 := glisp.List("a","b","c","d","e")
fmt.Println(glisp.ToString(glisp.Member(f,lst1))) // This prints "(c d e)"
Fold will apply f to the first element of lst1 and all of lst2 and the result will then be used to apply f to the second value of lst1 and the returned value, etc.
This is the same as f(Nth(n),...f(Car(Car(n)),f(Car(n),lst))) ....)
For example:
f := func(val1, val2 interface{}) interface{} {
if glisp.IsInt(val1) && glisp.IsInt(val2) {
return val1.(int) + val2.(int) // Just return the sum of the two arguments
}
return 0
}
lst1 := glisp.List(1,2,3,4,5)
fmt.Println(ToString(glisp.Fold(f,lst1,0))) // This will output 15
// Fold will first call f(1,0) where 0 was provided by the call to fold
// this produces 1 because 1+0 = 1
// Now Fold calls f(2,1) where 1 was returned in the previous step
// this produces 3 because 2+1 = 3
// Now Fold calls f(3,3) which produces 6
// Then Fold calls f(4,6) which produces 10
// And lastly Fold calls f(5,10) which returns 15
Acons will cons val1 and val2 together and add that to the front of lst for a Association list.
For example:
// Let's assume lst1 holds the list (("a" . 1) ("b" . 2))
lst1 = glisp.Acons("c",3,lst1) // Now lst1 holds (("c" . 3) ("a" . 1) ("b" . 2))
Assoc will search for the first element where the Car of that element will return true when f is applied. For example:
// Let's assum lst1 holds the list (("a" . 1) ("b" . 2) ("c" . 3) ("d" . 4))
f := func(val interface{}) bool {
return IsString(val) && val.(string)=="b"
}
fmt.Println(glisp.Assoc(f,lst1)) // This will print "(b 2)"