package iterable
import (
"container/list"
"container/vector"
)
type Iterable interface {
Iter() <-chan interface{}
}
func not(f func(interface{}) bool) func(interface{}) bool {
return func(e interface{}) bool { return !f(e) }
}
func All(iter Iterable, f func(interface{}) bool) bool {
for e := range iter.Iter() {
if !f(e) {
return false
}
}
return true
}
func Any(iter Iterable, f func(interface{}) bool) bool {
return !All(iter, not(f))
}
func Data(iter Iterable) []interface{} {
var v vector.Vector
for e := range iter.Iter() {
v.Push(e)
}
return v
}
type filteredIterable struct {
it Iterable
f func(interface{}) bool
}
func (f *filteredIterable) iterate(out chan<- interface{}) {
for e := range f.it.Iter() {
if f.f(e) {
out <- e
}
}
close(out)
}
func (f *filteredIterable) Iter() <-chan interface{} {
ch := make(chan interface{})
go f.iterate(ch)
return ch
}
func Filter(iter Iterable, f func(interface{}) bool) Iterable {
return &filteredIterable{iter, f}
}
func Find(iter Iterable, f func(interface{}) bool) interface{} {
for e := range Filter(iter, f).Iter() {
return e
}
return nil
}
type Injector func(interface{}, interface{}) interface{}
func Inject(iter Iterable, initial interface{}, f Injector) interface{} {
acc := initial
for e := range iter.Iter() {
acc = f(acc, e)
}
return acc
}
type mappedIterable struct {
it Iterable
f func(interface{}) interface{}
}
func (m *mappedIterable) iterate(out chan<- interface{}) {
for e := range m.it.Iter() {
out <- m.f(e)
}
close(out)
}
func (m *mappedIterable) Iter() <-chan interface{} {
ch := make(chan interface{})
go m.iterate(ch)
return ch
}
func Map(iter Iterable, f func(interface{}) interface{}) Iterable {
return &mappedIterable{iter, f}
}
func Partition(iter Iterable, f func(interface{}) bool) (Iterable, Iterable) {
return Filter(iter, f), Filter(iter, not(f))
}
type Func func(chan<- interface{})
func (f Func) Iter() <-chan interface{} {
ch := make(chan interface{})
go f(ch)
return ch
}
func Take(iter Iterable, n int) Iterable { return Slice(iter, 0, n) }
func TakeWhile(iter Iterable, f func(interface{}) bool) Iterable {
return Func(func(ch chan<- interface{}) {
for v := range iter.Iter() {
if !f(v) {
break
}
ch <- v
}
close(ch)
})
}
func Drop(iter Iterable, n int) Iterable {
return Func(func(ch chan<- interface{}) {
m := n
for v := range iter.Iter() {
if m > 0 {
m--
continue
}
ch <- v
}
close(ch)
})
}
func DropWhile(iter Iterable, f func(interface{}) bool) Iterable {
return Func(func(ch chan<- interface{}) {
drop := true
for v := range iter.Iter() {
if drop {
if f(v) {
continue
}
drop = false
}
ch <- v
}
close(ch)
})
}
func Cycle(iter Iterable) Iterable {
return Func(func(ch chan<- interface{}) {
for {
for v := range iter.Iter() {
ch <- v
}
}
})
}
func Chain(args []Iterable) Iterable {
return Func(func(ch chan<- interface{}) {
for _, e := range args {
for v := range e.Iter() {
ch <- v
}
}
close(ch)
})
}
func Zip(args []Iterable) Iterable {
return Func(func(ch chan<- interface{}) {
defer close(ch)
if len(args) == 0 {
return
}
iters := make([]<-chan interface{}, len(args))
for i := 0; i < len(iters); i++ {
iters[i] = args[i].Iter()
}
for {
out := make([]interface{}, len(args))
for i, v := range iters {
out[i] = <-v
if closed(v) {
return
}
}
ch <- out
}
})
}
func ZipWith2(f func(c, d interface{}) interface{}, a, b Iterable) Iterable {
return Map(Zip([]Iterable{a, b}), func(a1 interface{}) interface{} {
arr := a1.([]interface{})
return f(arr[0], arr[1])
})
}
func ZipWith3(f func(d, e, f interface{}) interface{}, a, b, c Iterable) Iterable {
return Map(Zip([]Iterable{a, b, c}), func(a1 interface{}) interface{} {
arr := a1.([]interface{})
return f(arr[0], arr[1], arr[2])
})
}
func Slice(iter Iterable, start, stop int) Iterable {
return Func(func(ch chan<- interface{}) {
defer close(ch)
i := 0
for v := range iter.Iter() {
switch {
case i >= stop:
return
case i >= start:
ch <- v
}
i++
}
})
}
func Repeat(v interface{}) Iterable {
return Func(func(ch chan<- interface{}) {
for {
ch <- v
}
})
}
func RepeatTimes(v interface{}, n int) Iterable {
return Func(func(ch chan<- interface{}) {
for i := 0; i < n; i++ {
ch <- v
}
close(ch)
})
}
type Group struct {
Key interface{}
Vals Iterable
}
type Grouper interface {
Key(interface{}) interface{}
Equal(a, b interface{}) bool
}
func GroupBy(iter Iterable, k Grouper) Iterable {
return Func(func(ch chan<- interface{}) {
var curkey interface{}
var lst *list.List
for v := range iter.Iter() {
kv := k.Key(v)
if lst == nil || !k.Equal(curkey, kv) {
if lst != nil {
ch <- Group{curkey, lst}
}
lst = list.New()
curkey = kv
}
lst.PushBack(v)
}
if lst != nil {
ch <- Group{curkey, lst}
}
close(ch)
})
}
func Unique(iter Iterable, id Grouper) Iterable {
return Map(GroupBy(iter, id), func(v interface{}) interface{} { return v.(Group).Key })
}