forked from zhemao/glisp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy paths-array.go
115 lines (96 loc) · 2.29 KB
/
s-array.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package glisp
import (
"errors"
"fmt"
)
type SexpArray []Sexp
func (arr SexpArray) SexpString() string {
if len(arr) == 0 {
return "[]"
}
str := "[" + arr[0].SexpString()
for _, sexp := range arr[1:] {
str += " " + sexp.SexpString()
}
str += "]"
return str
}
func MapArray(env *Environment, fun *SexpFunction, arr SexpArray) (SexpArray, error) {
result := make([]Sexp, len(arr))
var err error
for i := range arr {
result[i], err = env.Apply(fun, arr[i:i+1])
if err != nil {
return SexpArray(result), err
}
}
return SexpArray(result), nil
}
func FlatMapArray(env *Environment, fun *SexpFunction, arr SexpArray) (SexpArray, error) {
result := make([]Sexp, 0, len(arr))
for i := range arr {
res, err := env.Apply(fun, arr[i:i+1])
if err != nil {
return SexpArray(result), err
}
if res == SexpNull {
continue
}
if !IsArray(res) {
return SexpArray(result), errors.New("flatmap function must return array")
}
arr := res.(SexpArray)
result = append(result, arr...)
}
return SexpArray(result), nil
}
func FilterArray(env *Environment, fun *SexpFunction, arr SexpArray) (SexpArray, error) {
result := make([]Sexp, 0, len(arr))
for i := range arr {
item := arr[i]
ret, err := env.Apply(fun, []Sexp{item})
if err != nil {
return SexpArray(result), err
}
pass, ok := ret.(SexpBool)
if !ok {
return SexpArray{}, errors.New("filter function must return boolean")
} else if pass {
result = append(result, item)
}
}
return SexpArray(result), nil
}
func ConcatArray(arr SexpArray, exprs ...Sexp) (SexpArray, error) {
ret := make(SexpArray, len(arr))
copy(ret, arr)
for _, expr := range exprs {
switch t := expr.(type) {
case SexpArray:
ret = append(ret, t...)
default:
return arr, fmt.Errorf("second argument(%s) is not an array", InspectType(expr))
}
}
return ret, nil
}
func FoldlArray(env *Environment, fun *SexpFunction, lst Sexp, acc Sexp) (Sexp, error) {
if lst == SexpNull {
return acc, nil
}
var list SexpArray
switch e := lst.(type) {
case SexpArray:
list = e
default:
return SexpNull, errors.New("not a array")
}
if len(list) == 0 {
return acc, nil
}
var err error
if acc, err = env.Apply(fun, []Sexp{list[0], acc}); err != nil {
return SexpNull, err
}
return FoldlArray(env, fun, SexpArray(list[1:]), acc)
}