1
0
mirror of https://github.com/golang/go synced 2024-11-26 02:27:56 -07:00

Consistency changes to container/* packages for iteration.

container/list:
  - change Iter to go over the list values

container/ring:
  - add Iter, drop Forward/Backward

container/vector:
  - add channel direction constraints

R=rsc,gri
APPROVED=rsc
DELTA=86  (23 added, 40 deleted, 23 changed)
OCL=33935
CL=34132
This commit is contained in:
David Symonds 2009-08-31 14:43:27 -07:00
parent 5a40a682e3
commit 8d29f7f1c9
7 changed files with 46 additions and 63 deletions

View File

@ -18,6 +18,16 @@ type Element struct {
Value interface {}; Value interface {};
} }
// Next returns the next list element or nil.
func (e *Element) Next() *Element {
return e.next
}
// Prev returns the previous list element or nil.
func (e *Element) Prev() *Element {
return e.prev
}
// List represents a doubly linked list. // List represents a doubly linked list.
type List struct { type List struct {
front, back *Element; front, back *Element;
@ -181,18 +191,15 @@ func (l *List) Len() int {
return l.len return l.len
} }
func (l *List) iterate(c chan <- *Element) { func (l *List) iterate(c chan<- interface {}) {
var next *Element; for e := l.front; e != nil; e = e.next {
for e := l.front; e != nil; e = next { c <- e.Value;
// Save next in case reader of c changes e.
next = e.next;
c <- e;
} }
close(c); close(c);
} }
func (l *List) Iter() <-chan *Element { func (l *List) Iter() <-chan interface {} {
c := make(chan *Element); c := make(chan interface {});
go l.iterate(c); go l.iterate(c);
return c return c
} }

View File

@ -114,8 +114,21 @@ func TestList(t *testing.T) {
checkListPointers(t, l, []*Element{ e1, e4, e3, e2 }); checkListPointers(t, l, []*Element{ e1, e4, e3, e2 });
l.Remove(e2); l.Remove(e2);
// Clear all elements by iterating // Check standard iteration.
sum := 0;
for e := range l.Iter() { for e := range l.Iter() {
if i, ok := e.(int); ok {
sum += i;
}
}
if sum != 4 {
t.Errorf("sum over l.Iter() = %d, want 4", sum);
}
// Clear all elements by iterating
var next *Element;
for e := l.Front(); e != nil; e = next {
next = e.Next();
l.Remove(e); l.Remove(e);
} }
checkListPointers(t, l, []*Element{}); checkListPointers(t, l, []*Element{});

View File

@ -138,37 +138,16 @@ func (r *Ring) Len() int {
} }
// Forward returns a channel for forward iteration through a ring. func (r *Ring) Iter() <-chan interface {} {
// Iteration is undefined if the ring is changed during iteration. c := make(chan interface {});
//
func (r *Ring) Forward() <-chan *Ring {
c := make(chan *Ring);
go func() { go func() {
if r != nil { if r != nil {
c <- r; c <- r.Value;
for p := r.Next(); p != r; p = p.next { for p := r.Next(); p != r; p = p.next {
c <- p; c <- p.Value;
} }
} }
close(c); close(c);
}(); }();
return c; return c
}
// Backward returns a channel for backward iteration through a ring.
// Iteration is undefined if the ring is changed during iteration.
//
func (r *Ring) Backward() <-chan *Ring {
c := make(chan *Ring);
go func() {
if r != nil {
c <- r;
for p := r.Prev(); p != r; p = p.prev {
c <- p;
}
}
close(c);
}();
return c;
} }

View File

@ -32,13 +32,13 @@ func verify(t *testing.T, r *Ring, N int, sum int) {
t.Errorf("r.Len() == %d; expected %d", n, N); t.Errorf("r.Len() == %d; expected %d", n, N);
} }
// forward iteration // iteration
n = 0; n = 0;
s := 0; s := 0;
for p := range r.Forward() { for p := range r.Iter() {
n++; n++;
if p.Value != nil { if p != nil {
s += p.Value.(int); s += p.(int);
} }
} }
if n != N { if n != N {
@ -48,22 +48,6 @@ func verify(t *testing.T, r *Ring, N int, sum int) {
t.Errorf("forward ring sum = %d; expected %d", s, sum); t.Errorf("forward ring sum = %d; expected %d", s, sum);
} }
// backward iteration
n = 0;
s = 0;
for p := range r.Backward() {
n++;
if p.Value != nil {
s += p.Value.(int);
}
}
if n != N {
t.Errorf("number of backward iterations == %d; expected %d", n, N);
}
if sum >= 0 && s != sum {
t.Errorf("backward ring sum = %d; expected %d", s, sum);
}
if r == nil { if r == nil {
return; return;
} }
@ -147,8 +131,8 @@ func makeN(n int) *Ring {
func sum(r *Ring) int { func sum(r *Ring) int {
s := 0; s := 0;
for p := range r.Forward() { for p := range r.Iter() {
s += p.Value.(int); s += p.(int);
} }
return s; return s;
} }

View File

@ -101,7 +101,7 @@ func (p *IntVector) Less(i, j int) bool {
// Iterate over all elements; driver for range // Iterate over all elements; driver for range
func (p *IntVector) iterate(c chan int) { func (p *IntVector) iterate(c chan<- int) {
for i, v := range p.a { for i, v := range p.a {
c <- v.(int) c <- v.(int)
} }
@ -110,7 +110,7 @@ func (p *IntVector) iterate(c chan int) {
// Channel iterator for range. // Channel iterator for range.
func (p *IntVector) Iter() chan int { func (p *IntVector) Iter() <-chan int {
c := make(chan int); c := make(chan int);
go p.iterate(c); go p.iterate(c);
return c; return c;

View File

@ -100,7 +100,7 @@ func (p *StringVector) Less(i, j int) bool {
// Iterate over all elements; driver for range // Iterate over all elements; driver for range
func (p *StringVector) iterate(c chan string) { func (p *StringVector) iterate(c chan<- string) {
for i, v := range p.a { for i, v := range p.a {
c <- v.(string) c <- v.(string)
} }
@ -109,7 +109,7 @@ func (p *StringVector) iterate(c chan string) {
// Channel iterator for range. // Channel iterator for range.
func (p *StringVector) Iter() chan string { func (p *StringVector) Iter() <-chan string {
c := make(chan string); c := make(chan string);
go p.iterate(c); go p.iterate(c);
return c; return c;

View File

@ -228,7 +228,7 @@ func (p *Vector) Swap(i, j int) {
// Iterate over all elements; driver for range // Iterate over all elements; driver for range
func (p *Vector) iterate(c chan Element) { func (p *Vector) iterate(c chan<- Element) {
for i, v := range p.a { for i, v := range p.a {
c <- v c <- v
} }
@ -237,7 +237,7 @@ func (p *Vector) iterate(c chan Element) {
// Channel iterator for range. // Channel iterator for range.
func (p *Vector) Iter() chan Element { func (p *Vector) Iter() <-chan Element {
c := make(chan Element); c := make(chan Element);
go p.iterate(c); go p.iterate(c);
return c; return c;