| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // The iterable package provides several traversal and searching methods. | |
| // It can be used on anything that satisfies the Iterable interface, | |
| // including vector, though certain functions, such as Map, can also be used on | |
| // something that would produce an infinite amount of data. | |
| 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(interface {}) bool) bool { | |
| for e := range iter.Iter() { | |
| if !f(e) { | |
| return false | |
| } | |
| } | |
| return true | |
| } | |
| // Any tests whether f is true for at least one element of iter. | |
| 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); | |
| for e := range iter.Iter() { | |
| vec.Push(e) | |
| } | |
| 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 { | |
| 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; | |
| } | |
| // Map returns an Iterable that returns the result of applying f to each | |
| // element of iter. | |
| 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: | |
| // - Inject | |
| // - Zip |