summaryrefslogtreecommitdiff
path: root/src/lib/container/iterable.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/container/iterable.go')
-rw-r--r--src/lib/container/iterable.go64
1 files changed, 49 insertions, 15 deletions
diff --git a/src/lib/container/iterable.go b/src/lib/container/iterable.go
index 7963d14b5..a4a0d4c0f 100644
--- a/src/lib/container/iterable.go
+++ b/src/lib/container/iterable.go
@@ -10,15 +10,17 @@ package iterable
import "vector"
-
type Iterable interface {
// Iter should return a fresh channel each time it is called.
Iter() <-chan interface {}
}
+func not(f func(interface {}) bool) (func(interface {}) bool) {
+ return func(e interface {}) bool { return !f(e) }
+}
// All tests whether f is true for every element of iter.
-func All(iter Iterable, f func(e interface {}) bool) bool {
+func All(iter Iterable, f func(interface {}) bool) bool {
for e := range iter.Iter() {
if !f(e) {
return false
@@ -27,13 +29,11 @@ func All(iter Iterable, f func(e interface {}) bool) bool {
return true
}
-
// Any tests whether f is true for at least one element of iter.
-func Any(iter Iterable, f func(e interface {}) bool) bool {
- return !All(iter, func(e interface {}) bool { return !f(e) });
+func Any(iter Iterable, f func(interface {}) bool) bool {
+ return !All(iter, not(f))
}
-
// Data returns a slice containing the elements of iter.
func Data(iter Iterable) []interface {} {
vec := vector.New(0);
@@ -43,6 +43,41 @@ func Data(iter Iterable) []interface {} {
return vec.Data()
}
+// filteredIterable is a struct that implements Iterable with each element
+// passed through a filter.
+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;
+}
+
+// Filter returns an Iterable that returns the elements of iter that satisfy f.
+func Filter(iter Iterable, f func(interface {}) bool) Iterable {
+ return &filteredIterable{ iter, f }
+}
+
+// Find returns the first element of iter that satisfies f.
+// Returns nil if no such element is found.
+func Find(iter Iterable, f func(interface {}) bool) interface {} {
+ for e := range Filter(iter, f).Iter() {
+ return e
+ }
+ return nil
+}
// mappedIterable is a helper struct that implements Iterable, returned by Map.
type mappedIterable struct {
@@ -50,31 +85,30 @@ type mappedIterable struct {
f func(interface {}) interface {};
}
-
-func (m mappedIterable) iterate(out chan<- 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 {} {
+func (m *mappedIterable) Iter() <-chan interface {} {
ch := make(chan interface {});
go m.iterate(ch);
return ch;
}
-
// Map returns an Iterable that returns the result of applying f to each
// element of iter.
-func Map(iter Iterable, f func(e interface {}) interface {}) Iterable {
- return mappedIterable{ iter, f }
+func Map(iter Iterable, f func(interface {}) interface {}) Iterable {
+ return &mappedIterable{ iter, f }
}
+// Partition(iter, f) returns Filter(iter, f) and Filter(iter, !f).
+func Partition(iter Iterable, f func(interface {}) bool) (Iterable, Iterable) {
+ return Filter(iter, f), Filter(iter, not(f))
+}
// TODO:
-// - Find, Filter
// - Inject
-// - Partition
// - Zip