Removed Bleed and changed it to close the channel. Now functions in Seq() have to...
[bills-tools.git] / seq / seq.go
blob4999df7d711a908226f953be0e7d56848e7cf285
1 // Copyright 2010 Bill Burdick. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 //
5 package seq
7 import "fmt"
8 import "io"
9 import "os"
10 import "container/vector"
12 type Element interface{}
13 type SeqChan chan Element
14 type Sequence func()SeqChan
16 func IsSeq(s interface{}) bool {
17 _, test := s.(Sequence)
18 return test
21 // f must behave properly when the channel is closed, so that IsEmpty and First work properly
22 func Seq(f func(c SeqChan)) Sequence {
23 return func() SeqChan {
24 c := make(SeqChan)
25 go func() {
26 defer close(c)
27 f(c)
28 }()
29 return c
33 func From(el... interface{}) Sequence {
34 return Seq(func(c SeqChan) {Output(c, el...)})
37 func Output(c SeqChan, el... interface{}) {
38 for _, v := range el {
39 c <- v
43 func (s Sequence) First() Element {
44 c := s()
45 defer close(c)
46 return <- c
49 func (s Sequence) Rest() Sequence {
50 return func()SeqChan{
51 c := s()
52 <- c
53 return c
57 func (s Sequence) AddFirst(els... interface{}) Sequence {
58 return Seq(func(c SeqChan){
59 for el := range els {
60 c <- el
62 s.Output(c)
66 func (s Sequence) AddLast(els... interface{}) Sequence {
67 return Seq(func(c SeqChan){
68 s.Output(c)
69 for el := range els {
70 c <- el
75 func (s Sequence) IsEmpty() bool {
76 c := s()
77 <- c
78 result := closed(c)
79 if !result {defer close(c)}
80 return result
83 func (s Sequence) Append(s2 Sequence) Sequence {
84 return Seq(func(c SeqChan){
85 s.Output(c)
86 s2.Output(c)
90 func (s Sequence) Len() int {
91 len := 0
92 c := s()
93 for !closed(c) {
94 <- c
95 len++
97 return len - 1
100 func (s Sequence) Output(c chan Element) {
101 for el := range s() {
102 c <- el
106 func Upto(limit int) Sequence {
107 return Seq(func(c SeqChan) {
108 for i := 0; i < limit; i++ {
109 c <- i
114 func (s Sequence) Filter(filter func(e Element)bool) Sequence {
115 return Seq(func(c SeqChan){
116 for el := range s() {
117 if filter(el) {
118 c <- el
124 func (s Sequence) Do(f func(el Element)) {
125 for v := range s() {
126 f(v)
130 func (s Sequence) Map(f func(i Element)Element) Sequence {
131 return Seq(func(c SeqChan) {
132 for v := range s() {
133 c <- f(v)
138 func (s Sequence) FlatMap(f func(i Element) Sequence) Sequence {
139 return Seq(func(c SeqChan) {
140 for v := range s() {
141 for sub := range f(v)() {
142 c <- sub
148 func (s Sequence) Fold(init Element, f func(acc, el Element)Element) Element {
149 for el := range s() {
150 init = f(init, el)
152 return init
155 //maybe convert this to use an accumulator instead of append?
156 func (s Sequence) Combinations(number int) Sequence {
157 if number == 0 || s.IsEmpty() {return From(From())}
158 return s.Rest().Combinations(number - 1).Map(func(el Element)Element{
159 return el.(Sequence).AddFirst(s.First())
160 }).Append(s.Rest().Combinations(number))
163 //returns the product of the Sequences contained in sequences
164 func (sequences Sequence) Product() Sequence {
165 return sequences.Fold(From(From()), func(acc, el Element)Element{
166 return el.(Sequence).peelOnto(acc.(Sequence))
167 }).(Sequence)
170 func (s Sequence) peelOnto(seq Sequence) Sequence {
171 return seq.FlatMap(func(old Element)Sequence{
172 return s.Map(func(i Element) Element {
173 return old.(Sequence).Append(From(i))
178 func (s Sequence) Reify() Sequence {
179 vec := vector.Vector(make([]interface{}, 0, 128))
180 for v := range s() {
181 sv, is := v.(Sequence)
182 if is {
183 vec.Push(sv.Reify())
184 } else {
185 vec.Push(v)
188 return From([]interface{}(vec)...)
191 func (s Sequence) Prettyln(names map[Element]string, writer... io.Writer) {
192 if len(writer) == 0 {
193 writer = []io.Writer{os.Stdout}
195 s.Pretty(names, writer...)
196 fmt.Fprintln(writer[0])
198 func (s Sequence) Pretty(names map[Element]string, writer... io.Writer) {
199 if len(writer) == 0 {
200 writer = []io.Writer{os.Stdout}
202 s.prettyLevel(0, names, writer[0])
205 //This is pretty ugly :)
206 func (s Sequence) prettyLevel(level int, names map[Element]string, w io.Writer) {
207 name, hasName := names[s]
208 if hasName {
209 fmt.Fprint(w, name)
210 } else {
211 c := s()
212 fmt.Fprintf(w, "%*s%s", level, "", "[")
213 first := true
214 innerSeq := false
215 named := false
216 for v := range c {
217 _, named = names[v]
218 _,innerSeq = v.(Sequence)
219 if first {
220 first = false
221 if !named && innerSeq {
222 fmt.Fprintln(w)
224 } else if !named && innerSeq {
225 fmt.Fprintln(w, ",")
226 } else {
227 fmt.Fprint(w, ", ")
229 if innerSeq {
230 v.(Sequence).prettyLevel(level + 4, names, w)
231 } else {
232 fmt.Fprintf(w, "%v", v)
235 if innerSeq {
236 if !named {
237 fmt.Fprintf(w, "\n%*s", level, "")
240 fmt.Fprintf(w, "]")