Skip to content

Commit

Permalink
Merge pull request #14 from koss-null/no_copy_on_slice_creation
Browse files Browse the repository at this point in the history
v1.0.6 - No copy on slice creation
  • Loading branch information
koss-null authored Jan 21, 2024
2 parents 8e252b1 + 3162bf1 commit 532c8e3
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# FuncFrog

[![Go Report Card](https://goreportcard.com/badge/github.com/koss-null/funcfrog)](https://goreportcard.com/report/github.com/koss-null/lambda)
[![Go Report Card](https://goreportcard.com/badge/github.com/koss-null/funcfrog)](https://goreportcard.com/report/github.com/koss-null/funcfrog)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Coverage](https://raw.githubusercontent.com/koss-null/funcfrog/master/coverage_badge.png?raw=true)](coverage)

Expand Down
Binary file modified coverage_badge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 3 additions & 6 deletions internal/internalpipe/constructor.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@ const (
)

func Slice[T any](dt []T) Pipe[T] {
dtCp := make([]T, len(dt))
copy(dtCp, dt)

return Pipe[T]{
Fn: func(i int) (*T, bool) {
if i >= len(dtCp) {
if i >= len(dt) {
return nil, true
}
return &dtCp[i], false
return &dt[i], false
},
Len: len(dtCp),
Len: len(dt),
ValLim: notSet,
GoroutinesCnt: defaultParallelWrks,
}
Expand Down
32 changes: 32 additions & 0 deletions pkg/ff/ff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,38 @@ func TestMap(t *testing.T) {
}
}

func TestMapFilter(t *testing.T) {
a := []int{1, 2, 3, 4, 5, 6, 7, 8}

fn := func(x int) (string, bool) {
return strconv.Itoa(x), x%2 == 0
}

piper := MapFilter(a, fn).Do()

// Iterate through the values and test the output
expected := []string{"2", "4", "6", "8"}
for i, val := range piper {
require.Equal(t, expected[i], val, "Unexpected result for MapFilter")
}
}

func TestFilter(t *testing.T) {
a := []int{1, 2, 3, 4, 5}

fn := func(x *int) bool {
return *x%2 != 0
}

piper := Filter(a, fn).Do()

// Iterate through the values and test the output
expected := []int{1, 3, 5}
for i, val := range piper {
require.Equal(t, expected[i], val, "Unexpected result for Filter")
}
}

func TestReduce(t *testing.T) {
a := []int{1, 2, 3, 4, 5}

Expand Down
8 changes: 8 additions & 0 deletions pkg/ff/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ff

import "github.com/koss-null/funcfrog/pkg/pipe"

// Filter is a short way to create a Pipe from a slice of SrcT applying Filter function fn.
func Filter[SrcT any](a []SrcT, fn func(*SrcT) bool) pipe.Piper[SrcT] {
return pipe.Slice(a).Filter(fn)
}
8 changes: 8 additions & 0 deletions pkg/ff/map_filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ff

import "github.com/koss-null/funcfrog/pkg/pipe"

// MapFilter is a short way to create a Pipe of DstT from a slice of SrcT applying MapFilter function fn.
func MapFilter[SrcT, DstT any](a []SrcT, fn func(SrcT) (DstT, bool)) pipe.Piper[DstT] {
return pipe.MapFilter(pipe.Slice(a), fn)
}
27 changes: 27 additions & 0 deletions pkg/pipe/pipe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,33 @@ func TestPrefixMapNL(t *testing.T) {
require.Equal(t, []string{"1", "3", "4"}, res)
}

func TestPrefixMapFilter(t *testing.T) {
res := pipe.MapFilter(
pipe.Slice([]int{1, 2, 3, 4, 5}).Filter(
func(x *int) bool { return *x != 5 },
),
func(x int) (string, bool) {
return strconv.Itoa(x), x != 2
},
).Do()
require.Equal(t, []string{"1", "3", "4"}, res)
}

func TestPrefixMapFilterNL(t *testing.T) {
t.Parallel()

res := pipe.MapFilterNL(
pipe.Func(func(i int) (int, bool) {
a := [...]int{1, 2, 3, 4, 5}
return a[i], a[i] != 5
}),
func(x int) (string, bool) {
return strconv.Itoa(x), x != 2
},
).Gen(5).Do()
require.Equal(t, []string{"1", "3", "4"}, res)
}

func TestPrefixReduce(t *testing.T) {
t.Parallel()

Expand Down
46 changes: 44 additions & 2 deletions pkg/pipe/prefixpipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func Map[SrcT any, DstT any](
}

// MapNL applies function on a PiperNoLen of type SrcT and returns a Pipe of type DstT.
func MapNL[SrcT any, DstT any](
func MapNL[SrcT, DstT any](
p PiperNoLen[SrcT],
fn func(x SrcT) DstT,
) PiperNoLen[DstT] {
Expand All @@ -46,9 +46,51 @@ func MapNL[SrcT any, DstT any](
}}
}

// MapFilter applies function on a Piper of type SrcT and returns a Pipe of type DstT.
// fn returns a value of DstT type and true if this value is not skipped.
func MapFilter[SrcT, DstT any](
p Piper[SrcT],
fn func(x SrcT) (DstT, bool),
) Piper[DstT] {
pp := any(p).(entrails[SrcT]).Entrails()
return &Pipe[DstT]{internalpipe.Pipe[DstT]{
Fn: func(i int) (*DstT, bool) {
if obj, skipped := pp.Fn(i); !skipped {
dst, exist := fn(*obj)
return &dst, !exist
}
return nil, true
},
Len: pp.Len,
ValLim: pp.ValLim,
GoroutinesCnt: pp.GoroutinesCnt,
}}
}

// MapFilterNL applies function on a PiperNoLen of type SrcT and returns a Pipe of type DstT.
// fn returns a value of DstT type and true if this value is not skipped.
func MapFilterNL[SrcT, DstT any](
p PiperNoLen[SrcT],
fn func(x SrcT) (DstT, bool),
) PiperNoLen[DstT] {
pp := any(p).(entrails[SrcT]).Entrails()
return &PipeNL[DstT]{internalpipe.Pipe[DstT]{
Fn: func(i int) (*DstT, bool) {
if obj, skipped := pp.Fn(i); !skipped {
dst, exist := fn(*obj)
return &dst, !exist
}
return nil, true
},
Len: pp.Len,
ValLim: pp.ValLim,
GoroutinesCnt: pp.GoroutinesCnt,
}}
}

// Reduce applies reduce operation on Pipe of type SrcT and returns result of type DstT.
// initVal is an optional parameter to initialize a value that should be used on the first step of reduce.
func Reduce[SrcT any, DstT any](p Piper[SrcT], fn func(*DstT, *SrcT) DstT, initVal ...DstT) DstT {
func Reduce[SrcT, DstT any](p Piper[SrcT], fn func(*DstT, *SrcT) DstT, initVal ...DstT) DstT {
var init DstT
if len(initVal) > 0 {
init = initVal[0]
Expand Down

0 comments on commit 532c8e3

Please sign in to comment.