add Traverse to seq

This commit is contained in:
Brian Picciano 2014-10-24 13:32:28 -04:00
parent 024e0d2bec
commit 84c615ac58
2 changed files with 70 additions and 0 deletions

View File

@ -286,3 +286,27 @@ func DropWhile(pred func(types.Elem) bool, s Seq) Seq {
} }
return s return s
} }
// Runs pred on each element in the sequence, descending recursively if it
// encounters another Seq (without calling pred on that Seq). This amounts to a
// depth-first traverse. If pred ever returns false the traverse will stop.
// Returns false if the Traverse was stopped by pred, true otherwise.
func Traverse(pred func(types.Elem) bool, s Seq) bool {
var el types.Elem
var ok bool
for {
el, s, ok = s.FirstRest()
if !ok {
return true
}
var predRet bool
if inners, ok := el.(Seq); ok {
predRet = Traverse(pred, inners)
} else {
predRet = pred(el)
}
if !predRet {
return false
}
}
}

View File

@ -379,3 +379,49 @@ func TestDropWhile(t *T) {
assertEmpty(l, t) assertEmpty(l, t)
assertEmpty(nl, t) assertEmpty(nl, t)
} }
// Test Traversing a Seq until a given condition
func TestTraverse(t *T) {
var acc int
pred := func(el types.Elem) bool {
acc += el.(types.GoType).V.(int)
return true
}
l := NewList()
acc = 0
Traverse(pred, l)
assertValue(acc, 0, t)
l2 := NewList(elemSliceV(0, 1, 2, 3)...)
acc = 0
Traverse(pred, l2)
assertValue(acc, 6, t)
l3 := NewList(
types.GoType{1},
types.GoType{2},
NewList(elemSliceV(4, 5, 6)...),
types.GoType{3},
)
acc = 0
Traverse(pred, l3)
assertValue(acc, 21, t)
pred = func(el types.Elem) bool {
i := el.(types.GoType).V.(int)
if i > 4 {
return false
}
acc += i
return true
}
acc = 0
Traverse(pred, l2)
assertValue(acc, 6, t)
acc = 0
Traverse(pred, l3)
assertValue(acc, 7, t)
}