Commit e6ecf976 authored by Russ Cox's avatar Russ Cox

exp/iterable: delete

Package iterable has outlived its utility.

It is an interesting demonstration, but it encourages
people to use iteration over channels where simple
iteration over array indices or a linked list would be
cheaper, simpler, and have fewer races.

R=dsymonds, r
CC=golang-dev
https://golang.org/cl/2436041
parent f7512989
......@@ -63,7 +63,6 @@ DIRS=\
exp/draw\
exp/draw/x11\
exp/eval\
exp/iterable\
expvar\
flag\
fmt\
......
......@@ -180,19 +180,6 @@ func (l *List) MoveToBack(e *Element) {
// Len returns the number of elements in the list.
func (l *List) Len() int { return l.len }
func (l *List) iterate(c chan<- interface{}) {
for e := l.front; e != nil; e = e.next {
c <- e.Value
}
close(c)
}
func (l *List) Iter() <-chan interface{} {
c := make(chan interface{})
go l.iterate(c)
return c
}
// PushBackList inserts each element of ol at the back of the list.
func (l *List) PushBackList(ol *List) {
last := ol.Back()
......
......@@ -116,8 +116,8 @@ func TestList(t *testing.T) {
// Check standard iteration.
sum := 0
for e := range l.Iter() {
if i, ok := e.(int); ok {
for e := l.Front(); e != nil; e = e.Next() {
if i, ok := e.Value.(int); ok {
sum += i
}
}
......@@ -141,7 +141,8 @@ func checkList(t *testing.T, l *List, es []interface{}) {
return
}
i := 0
for le := range l.Iter() {
for e := l.Front(); e != nil; e = e.Next() {
le := e.Value.(int)
if le != es[i] {
t.Errorf("elt #%d has value=%v, want %v", i, le, es[i])
}
......
# 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.
include ../../../Make.inc
TARG=exp/iterable
GOFILES=\
array.go\
iterable.go\
include ../../../Make.pkg
// 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.
package iterable
// This file implements the Iterable interface on some primitive types.
type ByteArray []byte
func (a ByteArray) Iter() <-chan interface{} {
ch := make(chan interface{})
go func() {
for _, e := range a {
ch <- e
}
close(ch)
}()
return ch
}
type IntArray []int
func (a IntArray) Iter() <-chan interface{} {
ch := make(chan interface{})
go func() {
for _, e := range a {
ch <- e
}
close(ch)
}()
return ch
}
type FloatArray []float
func (a FloatArray) Iter() <-chan interface{} {
ch := make(chan interface{})
go func() {
for _, e := range a {
ch <- e
}
close(ch)
}()
return ch
}
type StringArray []string
func (a StringArray) Iter() <-chan interface{} {
ch := make(chan interface{})
go func() {
for _, e := range a {
ch <- e
}
close(ch)
}()
return ch
}
type UintArray []uint
func (a UintArray) Iter() <-chan interface{} {
ch := make(chan interface{})
go func() {
for _, e := range a {
ch <- e
}
close(ch)
}()
return ch
}
// 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 (
"container/list"
"container/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{} {
var v vector.Vector
for e := range iter.Iter() {
v.Push(e)
}
return v
}
// 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
}
// Injector is a type representing a function that takes two arguments,
// an accumulated value and an element, and returns the next accumulated value.
// See the Inject function.
type Injector func(interface{}, interface{}) interface{}
// Inject combines the elements of iter by repeatedly calling f with an
// accumulated value and each element in order. The starting accumulated value
// is initial, and after each call the accumulated value is set to the return
// value of f. For instance, to compute a sum:
// var arr IntArray = []int{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// sum := iterable.Inject(arr, 0,
// func(ax interface {}, x interface {}) interface {} {
// return ax.(int) + x.(int) }).(int)
func Inject(iter Iterable, initial interface{}, f Injector) interface{} {
acc := initial
for e := range iter.Iter() {
acc = f(acc, e)
}
return acc
}
// 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))
}
// A Func is a function that, when called, sends the
// iterable values on a channel.
type Func func(chan<- interface{})
// Iter creates and returns a new channel; it starts a
// goroutine running f to send values to the channel.
func (f Func) Iter() <-chan interface{} {
ch := make(chan interface{})
go f(ch)
return ch
}
// Take returns an Iterable that contains the first n elements of iter.
func Take(iter Iterable, n int) Iterable { return Slice(iter, 0, n) }
// TakeWhile returns an Iterable that contains elements from iter while f is true.
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)
})
}
// Drop returns an Iterable that returns each element of iter after the first n elements.
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)
})
}
// DropWhile returns an Iterable that returns each element of iter after the initial sequence for which f returns true.
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)
})
}
// Cycle repeats the values of iter in order infinitely.
func Cycle(iter Iterable) Iterable {
return Func(func(ch chan<- interface{}) {
for {
for v := range iter.Iter() {
ch <- v
}
}
})
}
// Chain returns an Iterable that concatenates all values from the specified Iterables.
func Chain(args []Iterable) Iterable {
return Func(func(ch chan<- interface{}) {
for _, e := range args {
for v := range e.Iter() {
ch <- v
}
}
close(ch)
})
}
// Zip returns an Iterable of []interface{} consisting of the next element from
// each input Iterable. The length of the returned Iterable is the minimum of
// the lengths of the input Iterables.
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
}
})
}
// ZipWith returns an Iterable containing the result of executing f using arguments read from a and b.
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])
})
}
// ZipWith returns an Iterable containing the result of executing f using arguments read from a, b and c.
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])
})
}
// Slice returns an Iterable that contains the elements from iter
// with indexes in [start, stop).
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++
}
})
}
// Repeat generates an infinite stream of v.
func Repeat(v interface{}) Iterable {
return Func(func(ch chan<- interface{}) {
for {
ch <- v
}
})
}
// RepeatTimes generates a stream of n copies of v.
func RepeatTimes(v interface{}, n int) Iterable {
return Func(func(ch chan<- interface{}) {
for i := 0; i < n; i++ {
ch <- v
}
close(ch)
})
}
// Group is the type for elements returned by the GroupBy function.
type Group struct {
Key interface{} // key value for matching items
Vals Iterable // Iterable for receiving values in the group
}
// Key defines the interface required by the GroupBy function.
type Grouper interface {
// Return the key for the given value
Key(interface{}) interface{}
// Compute equality for the given keys
Equal(a, b interface{}) bool
}
// GroupBy combines sequences of logically identical values from iter using k
// to generate a key to compare values. Each value emitted by the returned
// Iterable is of type Group, which contains the key used for matching the
// values for the group, and an Iterable for retrieving all the values in the
// group.
func GroupBy(iter Iterable, k Grouper) Iterable {
return Func(func(ch chan<- interface{}) {
var curkey interface{}
var lst *list.List
// Basic strategy is to read one group at a time into a list prior to emitting the Group value
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)
})
}
// Unique removes duplicate values which occur consecutively using id to compute keys.
func Unique(iter Iterable, id Grouper) Iterable {
return Map(GroupBy(iter, id), func(v interface{}) interface{} { return v.(Group).Key })
}
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment