Skip to content

Commit

Permalink
ForEach functions
Browse files Browse the repository at this point in the history
ForEach pack of functions. These might be really helpful.
  • Loading branch information
kalaninja committed Jan 6, 2017
1 parent 09a5b98 commit 95469b0
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
71 changes: 71 additions & 0 deletions result.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,77 @@ func (q Query) FirstWithT(predicateFn interface{}) interface{} {
return q.FirstWith(predicateFunc)
}

// ForEach performs the specified action on each element of a collection.
func (q Query) ForEach(action func(interface{})) {
next := q.Iterate()

for item, ok := next(); ok; item, ok = next() {
action(item)
}
}

// ForEachT is the typed version of ForEach.
//
// - actionFn is of type "func(TSource)"
//
// NOTE: ForEach has better performance than ForEachT.
func (q Query) ForEachT(actionFn interface{}) {
actionGenericFunc, err := newGenericFunc(
"ForEachT", "actionFn", actionFn,
simpleParamValidator(newElemTypeSlice(new(genericType)), nil),
)

if err != nil {
panic(err)
}

actionFunc := func(item interface{}) {
actionGenericFunc.Call(item)
}

q.ForEach(actionFunc)
}

// ForEachIndexed performs the specified action on each element of a collection.
//
// The first argument to action represents the zero-based index of that
// element in the source collection. This can be useful if the elements are in a
// known order and you want to do something with an element at a particular
// index, for example. It can also be useful if you want to retrieve the index
// of one or more elements. The second argument to action represents the
// element to process.
func (q Query) ForEachIndexed(action func(int, interface{})) {
next := q.Iterate()
index := 0

for item, ok := next(); ok; item, ok = next() {
action(index, item)
index++
}
}

// ForEachIndexedT is the typed version of ForEachIndexed.
//
// - actionFn is of type "func(int, TSource)"
//
// NOTE: ForEachIndexed has better performance than ForEachIndexedT.
func (q Query) ForEachIndexedT(actionFn interface{}) {
actionGenericFunc, err := newGenericFunc(
"ForEachIndexedT", "actionFn", actionFn,
simpleParamValidator(newElemTypeSlice(new(int), new(genericType)), nil),
)

if err != nil {
panic(err)
}

actionFunc := func(index int, item interface{}) {
actionGenericFunc.Call(index, item)
}

q.ForEachIndexed(actionFunc)
}

// Last returns the last element of a collection.
func (q Query) Last() (r interface{}) {
next := q.Iterate()
Expand Down
54 changes: 54 additions & 0 deletions result_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,60 @@ func TestFirstWithT_PanicWhenPredicateFnIsInvalid(t *testing.T) {
})
}

func TestForEach(t *testing.T) {
tests := []struct {
input interface{}
want interface{}
}{
{[5]int{1, 2, 2, 35, 111}, []int{1, 2, 2, 35, 111}},
{[]int{}, []int{}},
}

for _, test := range tests {
output := []int{}
From(test.input).ForEach(func(item interface{}) {
output = append(output, item.(int))
})

if !reflect.DeepEqual(output, test.want) {
t.Fatalf("From(%#v).ForEach()=%#v expected=%#v", test.input, output, test.want)
}
}
}

func TestForEachT_PanicWhenActionFnIsInvalid(t *testing.T) {
mustPanicWithError(t, "ForEachT: parameter [actionFn] has a invalid function signature. Expected: 'func(T)', actual: 'func(int,int)'", func() {
From([]int{1, 1, 1, 2, 1, 2, 3, 4, 2}).ForEachT(func(item, idx int) { item = item + 2 })
})
}

func TestForEachIndexed(t *testing.T) {
tests := []struct {
input interface{}
want interface{}
}{
{[5]int{1, 2, 2, 35, 111}, []int{1, 3, 4, 38, 115}},
{[]int{}, []int{}},
}

for _, test := range tests {
output := []int{}
From(test.input).ForEachIndexed(func(index int, item interface{}) {
output = append(output, item.(int)+index)
})

if !reflect.DeepEqual(output, test.want) {
t.Fatalf("From(%#v).ForEachIndexed()=%#v expected=%#v", test.input, output, test.want)
}
}
}

func TestForEachIndexedT_PanicWhenActionFnIsInvalid(t *testing.T) {
mustPanicWithError(t, "ForEachIndexedT: parameter [actionFn] has a invalid function signature. Expected: 'func(int,T)', actual: 'func(int)'", func() {
From([]int{1, 1, 1, 2, 1, 2, 3, 4, 2}).ForEachIndexedT(func(item int) { item = item + 2 })
})
}

func TestLast(t *testing.T) {
tests := []struct {
input interface{}
Expand Down

0 comments on commit 95469b0

Please sign in to comment.