From f541d8b459301d53766255cb773b3c62aade00be Mon Sep 17 00:00:00 2001 From: halprin Date: Sat, 30 Oct 2021 23:28:36 -0600 Subject: [PATCH 1/9] Move generator package to be an internal one --- begin.go | 2 +- begin_test.go | 2 +- example_test.go | 2 +- intermediate/link_chain.go | 2 +- intermediate/link_chain_parallel.go | 2 +- intermediate/link_chain_parallel_test.go | 2 +- intermediate/link_chain_test.go | 2 +- intermediate/link_termination.go | 2 +- intermediate/link_termination_test.go | 2 +- {generator => internal/generator}/generator.go | 0 {generator => internal/generator}/generator_test.go | 0 11 files changed, 9 insertions(+), 9 deletions(-) rename {generator => internal/generator}/generator.go (100%) rename {generator => internal/generator}/generator_test.go (100%) diff --git a/begin.go b/begin.go index 01514f8..bf5742a 100644 --- a/begin.go +++ b/begin.go @@ -1,8 +1,8 @@ package rangechain import ( - "github.com/halprin/rangechain/generator" "github.com/halprin/rangechain/intermediate" + "github.com/halprin/rangechain/internal/generator" ) // FromSlice starts the chain with the supplied slice. diff --git a/begin_test.go b/begin_test.go index deb0308..ec667ca 100644 --- a/begin_test.go +++ b/begin_test.go @@ -1,7 +1,7 @@ package rangechain import ( - "github.com/halprin/rangechain/generator" + "github.com/halprin/rangechain/internal/generator" "github.com/stretchr/testify/assert" "testing" ) diff --git a/example_test.go b/example_test.go index 728a1b6..a7febf6 100644 --- a/example_test.go +++ b/example_test.go @@ -2,7 +2,7 @@ package rangechain import ( "fmt" - "github.com/halprin/rangechain/generator" + "github.com/halprin/rangechain/internal/generator" "testing" ) diff --git a/intermediate/link_chain.go b/intermediate/link_chain.go index 1ab0267..efef53d 100644 --- a/intermediate/link_chain.go +++ b/intermediate/link_chain.go @@ -2,8 +2,8 @@ package intermediate import ( "errors" - "github.com/halprin/rangechain/generator" "github.com/halprin/rangechain/helper" + "github.com/halprin/rangechain/internal/generator" "sort" ) diff --git a/intermediate/link_chain_parallel.go b/intermediate/link_chain_parallel.go index 7fadf3c..8885942 100644 --- a/intermediate/link_chain_parallel.go +++ b/intermediate/link_chain_parallel.go @@ -1,6 +1,6 @@ package intermediate -import "github.com/halprin/rangechain/generator" +import "github.com/halprin/rangechain/internal/generator" // MapParallel will run the `mapFunction` parameter function against all the values in the chain in parallel. In that function, return what you want to change the value into or an optional error if an error is encountered. There is overhead to running in parallel so benchmark to ensure you benefit from this version. func (receiver *Link) MapParallel(mapFunction func(interface{}) (interface{}, error)) *Link { diff --git a/intermediate/link_chain_parallel_test.go b/intermediate/link_chain_parallel_test.go index d6f3741..7a3f3ee 100644 --- a/intermediate/link_chain_parallel_test.go +++ b/intermediate/link_chain_parallel_test.go @@ -2,8 +2,8 @@ package intermediate import ( "errors" - "github.com/halprin/rangechain/generator" "github.com/halprin/rangechain/helper" + "github.com/halprin/rangechain/internal/generator" "github.com/stretchr/testify/assert" "testing" ) diff --git a/intermediate/link_chain_test.go b/intermediate/link_chain_test.go index d5e256c..bcc82a6 100644 --- a/intermediate/link_chain_test.go +++ b/intermediate/link_chain_test.go @@ -2,8 +2,8 @@ package intermediate import ( "errors" - "github.com/halprin/rangechain/generator" "github.com/halprin/rangechain/helper" + "github.com/halprin/rangechain/internal/generator" "github.com/stretchr/testify/assert" "testing" ) diff --git a/intermediate/link_termination.go b/intermediate/link_termination.go index e04b566..dde428b 100644 --- a/intermediate/link_termination.go +++ b/intermediate/link_termination.go @@ -2,7 +2,7 @@ package intermediate import ( "errors" - "github.com/halprin/rangechain/generator" + "github.com/halprin/rangechain/internal/generator" ) // Slice serializes the chain into a slice and returns it. Also returns an error if any previous chain method generated an error. If an error is returned, the slice is filled in until the error was encountered. diff --git a/intermediate/link_termination_test.go b/intermediate/link_termination_test.go index bc53b66..0edb8dc 100644 --- a/intermediate/link_termination_test.go +++ b/intermediate/link_termination_test.go @@ -3,8 +3,8 @@ package intermediate import ( "errors" - "github.com/halprin/rangechain/generator" "github.com/halprin/rangechain/helper" + "github.com/halprin/rangechain/internal/generator" "github.com/stretchr/testify/assert" "sync" "testing" diff --git a/generator/generator.go b/internal/generator/generator.go similarity index 100% rename from generator/generator.go rename to internal/generator/generator.go diff --git a/generator/generator_test.go b/internal/generator/generator_test.go similarity index 100% rename from generator/generator_test.go rename to internal/generator/generator_test.go From 397f963f461cb14589e4bd0687c6a82e07a9a591 Mon Sep 17 00:00:00 2001 From: halprin Date: Sat, 30 Oct 2021 23:34:17 -0600 Subject: [PATCH 2/9] Move helper package to be an internal one --- intermediate/link_chain.go | 2 +- intermediate/link_chain_parallel_test.go | 2 +- intermediate/link_chain_test.go | 2 +- intermediate/link_termination_test.go | 2 +- internal/generator/generator.go | 2 +- {helper => internal/helper}/doc.go | 0 {helper => internal/helper}/interface.go | 0 {helper => internal/helper}/interface_test.go | 0 {helper => internal/helper}/set.go | 0 {helper => internal/helper}/set_test.go | 0 {helper => internal/helper}/type.go | 0 {helper => internal/helper}/type_test.go | 0 12 files changed, 5 insertions(+), 5 deletions(-) rename {helper => internal/helper}/doc.go (100%) rename {helper => internal/helper}/interface.go (100%) rename {helper => internal/helper}/interface_test.go (100%) rename {helper => internal/helper}/set.go (100%) rename {helper => internal/helper}/set_test.go (100%) rename {helper => internal/helper}/type.go (100%) rename {helper => internal/helper}/type_test.go (100%) diff --git a/intermediate/link_chain.go b/intermediate/link_chain.go index efef53d..4a3f1f9 100644 --- a/intermediate/link_chain.go +++ b/intermediate/link_chain.go @@ -2,8 +2,8 @@ package intermediate import ( "errors" - "github.com/halprin/rangechain/helper" "github.com/halprin/rangechain/internal/generator" + "github.com/halprin/rangechain/internal/helper" "sort" ) diff --git a/intermediate/link_chain_parallel_test.go b/intermediate/link_chain_parallel_test.go index 7a3f3ee..e570143 100644 --- a/intermediate/link_chain_parallel_test.go +++ b/intermediate/link_chain_parallel_test.go @@ -2,8 +2,8 @@ package intermediate import ( "errors" - "github.com/halprin/rangechain/helper" "github.com/halprin/rangechain/internal/generator" + "github.com/halprin/rangechain/internal/helper" "github.com/stretchr/testify/assert" "testing" ) diff --git a/intermediate/link_chain_test.go b/intermediate/link_chain_test.go index bcc82a6..b472a8d 100644 --- a/intermediate/link_chain_test.go +++ b/intermediate/link_chain_test.go @@ -2,8 +2,8 @@ package intermediate import ( "errors" - "github.com/halprin/rangechain/helper" "github.com/halprin/rangechain/internal/generator" + "github.com/halprin/rangechain/internal/helper" "github.com/stretchr/testify/assert" "testing" ) diff --git a/intermediate/link_termination_test.go b/intermediate/link_termination_test.go index 0edb8dc..00e5530 100644 --- a/intermediate/link_termination_test.go +++ b/intermediate/link_termination_test.go @@ -3,8 +3,8 @@ package intermediate import ( "errors" - "github.com/halprin/rangechain/helper" "github.com/halprin/rangechain/internal/generator" + "github.com/halprin/rangechain/internal/helper" "github.com/stretchr/testify/assert" "sync" "testing" diff --git a/internal/generator/generator.go b/internal/generator/generator.go index f5fa99a..9457f1e 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -3,7 +3,7 @@ package generator import ( "errors" - "github.com/halprin/rangechain/helper" + "github.com/halprin/rangechain/internal/helper" "reflect" ) diff --git a/helper/doc.go b/internal/helper/doc.go similarity index 100% rename from helper/doc.go rename to internal/helper/doc.go diff --git a/helper/interface.go b/internal/helper/interface.go similarity index 100% rename from helper/interface.go rename to internal/helper/interface.go diff --git a/helper/interface_test.go b/internal/helper/interface_test.go similarity index 100% rename from helper/interface_test.go rename to internal/helper/interface_test.go diff --git a/helper/set.go b/internal/helper/set.go similarity index 100% rename from helper/set.go rename to internal/helper/set.go diff --git a/helper/set_test.go b/internal/helper/set_test.go similarity index 100% rename from helper/set_test.go rename to internal/helper/set_test.go diff --git a/helper/type.go b/internal/helper/type.go similarity index 100% rename from helper/type.go rename to internal/helper/type.go diff --git a/helper/type_test.go b/internal/helper/type_test.go similarity index 100% rename from helper/type_test.go rename to internal/helper/type_test.go From 68d2af19f24bf0f481f03c881de95d18a1fde766 Mon Sep 17 00:00:00 2001 From: halprin Date: Sat, 30 Oct 2021 23:39:49 -0600 Subject: [PATCH 3/9] Update code documentation since we have internal packages --- internal/generator/generator.go | 8 ++++---- internal/helper/doc.go | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) delete mode 100644 internal/helper/doc.go diff --git a/internal/generator/generator.go b/internal/generator/generator.go index 9457f1e..996ca0a 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -16,7 +16,7 @@ type MapTuple struct { Value interface{} } -// FromSlice is not meant to be called directly by external users. Creates a generator for a slice. +// FromSlice creates a generator for a slice. func FromSlice(slice interface{}) func() (interface{}, error) { if !helper.IsSlice(slice) { panic("non-slice type provided") @@ -25,7 +25,7 @@ func FromSlice(slice interface{}) func() (interface{}, error) { return generatorFromSliceOrArray(slice) } -// FromArray is not meant to be called directly by external users. Creates a generator for an array. +// FromArray creates a generator for an array. func FromArray(array interface{}) func() (interface{}, error) { if !helper.IsArray(array) { panic("non-array type provided") @@ -34,7 +34,7 @@ func FromArray(array interface{}) func() (interface{}, error) { return generatorFromSliceOrArray(array) } -// FromChannel is not meant to be called directly by external users. Creates a generator for a channel. +// FromChannel creates a generator for a channel. func FromChannel(channel interface{}) func() (interface{}, error) { if !helper.IsChannel(channel) { panic("non-channel type provided") @@ -54,7 +54,7 @@ func FromChannel(channel interface{}) func() (interface{}, error) { } } -// FromMap is not meant to be called directly by external users. Creates a generator for a map. +// FromMap creates a generator for a map. func FromMap(aMap interface{}) func() (interface{}, error) { if !helper.IsMap(aMap) { panic("non-map type provided") diff --git a/internal/helper/doc.go b/internal/helper/doc.go deleted file mode 100644 index 8dfffb4..0000000 --- a/internal/helper/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package helper is not meant to be used directly by external users. -package helper From ebb9469c1258137186ac8f1dd6352eef501110d8 Mon Sep 17 00:00:00 2001 From: halprin Date: Sat, 30 Oct 2021 23:52:21 -0600 Subject: [PATCH 4/9] Remove intermediate package and promote to rangechain package --- begin.go | 17 ++-- begin_test.go | 4 +- doc.go | 14 +++ intermediate/doc.go | 16 ---- intermediate/link.go => link.go | 6 +- intermediate/link_chain.go => link_chain.go | 22 ++--- ...hain_parallel.go => link_chain_parallel.go | 6 +- ...lel_test.go => link_chain_parallel_test.go | 10 +-- .../link_chain_test.go => link_chain_test.go | 44 +++++----- ...link_termination.go => link_termination.go | 2 +- ...nation_test.go => link_termination_test.go | 86 +++++++++---------- 11 files changed, 112 insertions(+), 115 deletions(-) delete mode 100644 intermediate/doc.go rename intermediate/link.go => link.go (67%) rename intermediate/link_chain.go => link_chain.go (94%) rename intermediate/link_chain_parallel.go => link_chain_parallel.go (98%) rename intermediate/link_chain_parallel_test.go => link_chain_parallel_test.go (94%) rename intermediate/link_chain_test.go => link_chain_test.go (92%) rename intermediate/link_termination.go => link_termination.go (99%) rename intermediate/link_termination_test.go => link_termination_test.go (93%) diff --git a/begin.go b/begin.go index bf5742a..d4caf7c 100644 --- a/begin.go +++ b/begin.go @@ -1,42 +1,41 @@ package rangechain import ( - "github.com/halprin/rangechain/intermediate" "github.com/halprin/rangechain/internal/generator" ) // FromSlice starts the chain with the supplied slice. // Chaining and terminating methods can now be called on the result. -func FromSlice(slice interface{}) *intermediate.Link { +func FromSlice(slice interface{}) *Link { sliceGenerator := generator.FromSlice(slice) - link := intermediate.NewLink(sliceGenerator) + link := newLink(sliceGenerator) return link } // FromArray starts the chain with the supplied array. // Chaining and terminating methods can now be called on the result. -func FromArray(array interface{}) *intermediate.Link { +func FromArray(array interface{}) *Link { arrayGenerator := generator.FromArray(array) - link := intermediate.NewLink(arrayGenerator) + link := newLink(arrayGenerator) return link } // FromChannel starts the chain with the supplied channel. // Chaining and terminating methods can now be called on the result. -func FromChannel(channel interface{}) *intermediate.Link { +func FromChannel(channel interface{}) *Link { channelGenerator := generator.FromChannel(channel) - link := intermediate.NewLink(channelGenerator) + link := newLink(channelGenerator) return link } // FromMap starts the chain with the supplied map. // Chaining and terminating methods can now be called on the result. The singular value used to represent the key and value pairs is `generator.MapTuple` of `github.com/halprin/rangechain/generator`. -func FromMap(aMap interface{}) *intermediate.Link { +func FromMap(aMap interface{}) *Link { mapGenerator := generator.FromMap(aMap) - link := intermediate.NewLink(mapGenerator) + link := newLink(mapGenerator) return link } diff --git a/begin_test.go b/begin_test.go index ec667ca..98b3e73 100644 --- a/begin_test.go +++ b/begin_test.go @@ -35,7 +35,7 @@ func TestFromChannel(t *testing.T) { innerInput := []string{"DogCows", "goes", "Moof!", "Do", "you", "like", "Clarus", "the", "DogCow?"} expectedOutput := []interface{}{"DogCows", "goes", "Moof!", "Do", "you", "like", "Clarus", "the", "DogCow?"} - input := createTestChannel(innerInput) + input := createTestStringChannel(innerInput) chain := FromChannel(input) slice, err := chain.Slice() @@ -81,7 +81,7 @@ func TestFromMap(t *testing.T) { assert.Nil(err) } -func createTestChannel(stringSlice []string) chan string { +func createTestStringChannel(stringSlice []string) chan string { stringChannel := make(chan string) go func() { diff --git a/doc.go b/doc.go index 0d43c47..e6d4edd 100644 --- a/doc.go +++ b/doc.go @@ -28,4 +28,18 @@ // // Notice `stringValue := value.(string)` above. This allows one to do the string concatenation on the next line because // the `+` operator doesn't work on an `interface{}` type. +// +// Continuing the Chain +// +// Chaining methods apply some modification to the values in the container values, but keeps the chain alive. +// This allows additional chaining methods to be subsequently called on the result. The subsequent chain methods operate +// on any changes performed by the previous chain method. +// Because modifications are lazily computed, none of the modifications from chaining methods are applied until _after_ a +// terminating method is called. +// +// Terminating the Chain +// +// Terminating methods also apply some modification, requests some information, or executes something on the values. +// They stop the chaining by returning an actual value. This value will depend on all the previous chaining methods being +// executed first. package rangechain diff --git a/intermediate/doc.go b/intermediate/doc.go deleted file mode 100644 index 0f1ab23..0000000 --- a/intermediate/doc.go +++ /dev/null @@ -1,16 +0,0 @@ -// Package intermediate is used continue or terminate the chain. -// -// Continuing the Chain -// -// Chaining methods apply some modification to the values in the container values, but keeps the chain alive. -// This allows additional chaining methods to be subsequently called on the result. The subsequent chain methods operate -// on any changes performed by the previous chain method. -// Because modifications are lazily computed, none of the modifications from chaining methods are applied until _after_ a -// terminating method is called. -// -// Terminating the Chain -// -// Terminating methods also apply some modification, requests some information, or executes something on the values. -// They stop the chaining by returning an actual value. This value will depend on all the previous chaining methods being -// executed first. -package intermediate diff --git a/intermediate/link.go b/link.go similarity index 67% rename from intermediate/link.go rename to link.go index af4449f..9400142 100644 --- a/intermediate/link.go +++ b/link.go @@ -1,12 +1,12 @@ -package intermediate +package rangechain // Link is not meant to be initialized directly by external users. Use the `From*` functions in the parent package rangechain. type Link struct { generator func() (interface{}, error) } -// NewLink is not meant to be called directly by external users. Use the `From*` functions in the parent package rangechain. -func NewLink(generator func() (interface{}, error)) *Link { +// newLink is not meant to be called directly by external users. Use the `From*` functions in the parent package rangechain. +func newLink(generator func() (interface{}, error)) *Link { return &Link{ generator: generator, } diff --git a/intermediate/link_chain.go b/link_chain.go similarity index 94% rename from intermediate/link_chain.go rename to link_chain.go index 4a3f1f9..bb356bd 100644 --- a/intermediate/link_chain.go +++ b/link_chain.go @@ -1,4 +1,4 @@ -package intermediate +package rangechain import ( "errors" @@ -18,7 +18,7 @@ func (receiver *Link) Map(mapFunction func(interface{}) (interface{}, error)) *L return mapFunction(valueToMap) } - return NewLink(mapGenerator) + return newLink(mapGenerator) } // Filter will run the `filterFunction` parameter function against all the values in the chain. In that function, on return of true, the value will stay, or on false, the value will be removed. @@ -41,7 +41,7 @@ func (receiver *Link) Filter(filterFunction func(interface{}) (bool, error)) *Li } } - return NewLink(filterGenerator) + return newLink(filterGenerator) } // Skip skips over the parameter `skipNumber` number of values and effectively removes them from the chain. Also skips over any errors previously generated. @@ -50,7 +50,7 @@ func (receiver *Link) Skip(skipNumber int) *Link { _, _ = receiver.generator() } - return NewLink(receiver.generator) + return newLink(receiver.generator) } // Limit stops the chain after the parameter `keepSize` number of values. Any elements afterward are effectively removed. @@ -72,7 +72,7 @@ func (receiver *Link) Limit(keepSize int) *Link { return currentValue, err } - return NewLink(limitGenerator) + return newLink(limitGenerator) } // Distinct removes any duplicates. @@ -94,7 +94,7 @@ func (receiver *Link) Distinct() *Link { } } - return NewLink(distinctGenerator) + return newLink(distinctGenerator) } // Flatten will iterate over all the values in the chain, but any value encountered that is a range-able container itself will also have its values iterated over first before continuing with the remaining values in the chain. Maps flatten to its `generator.MapTuple` key and value pairs. @@ -139,7 +139,7 @@ func (receiver *Link) Flatten() *Link { return innerValue, err } - return NewLink(flattenGenerator) + return newLink(flattenGenerator) } // Sort sorts the chain given the `Less` function returned from the `returnLessFunction` function parameter. The `returnLessFunction` function is called with the entire serialized chain as a slice and _returns_ a function that satisfies the same requirements as the Interface type's `Less` function (https://pkg.go.dev/sort#Interface). This method is expensive because it must serialize all the values into a slice first. @@ -151,7 +151,7 @@ func (receiver *Link) Sort(returnLessFunction func([]interface{}) func(int, int) generation := func() (interface{}, error) { return 0, err } - return NewLink(generation) + return newLink(generation) } lessFunction := returnLessFunction(serializedSlice) @@ -159,7 +159,7 @@ func (receiver *Link) Sort(returnLessFunction func([]interface{}) func(int, int) generation := generator.FromSlice(serializedSlice) - return NewLink(generation) + return newLink(generation) } // Reverse reverses the order of the chain. The last item will be first, and the first item will be last. This method is expensive because it must serialize all the values into a slice first. @@ -171,7 +171,7 @@ func (receiver *Link) Reverse() *Link { generation := func() (interface{}, error) { return 0, err } - return NewLink(generation) + return newLink(generation) } for startIndex, endIndex := 0, len(serializedSlice) - 1; startIndex <= endIndex; startIndex, endIndex = startIndex + 1, endIndex - 1 { @@ -180,5 +180,5 @@ func (receiver *Link) Reverse() *Link { generation := generator.FromSlice(serializedSlice) - return NewLink(generation) + return newLink(generation) } diff --git a/intermediate/link_chain_parallel.go b/link_chain_parallel.go similarity index 98% rename from intermediate/link_chain_parallel.go rename to link_chain_parallel.go index 8885942..8809872 100644 --- a/intermediate/link_chain_parallel.go +++ b/link_chain_parallel.go @@ -1,4 +1,4 @@ -package intermediate +package rangechain import "github.com/halprin/rangechain/internal/generator" @@ -27,7 +27,7 @@ func (receiver *Link) MapParallel(mapFunction func(interface{}) (interface{}, er return value, err } - return NewLink(mapGenerator) + return newLink(mapGenerator) } func mapFunctionAgainstEntireGenerator(generatorToParallelize func() (interface{}, error), mapFunction func(interface{}) (interface{}, error)) ([]chan interface{}, []chan error) { @@ -92,7 +92,7 @@ func (receiver *Link) FilterParallel(filterFunction func(interface{}) (bool, err } } - return NewLink(filterGenerator) + return newLink(filterGenerator) } func filterFunctionAgainstEntireGenerator(generatorToParallelize func() (interface{}, error), filterFunction func(interface{}) (bool, error)) ([]chan interface{}, []chan error) { diff --git a/intermediate/link_chain_parallel_test.go b/link_chain_parallel_test.go similarity index 94% rename from intermediate/link_chain_parallel_test.go rename to link_chain_parallel_test.go index e570143..5d1e9bc 100644 --- a/intermediate/link_chain_parallel_test.go +++ b/link_chain_parallel_test.go @@ -1,4 +1,4 @@ -package intermediate +package rangechain import ( "errors" @@ -18,7 +18,7 @@ func TestMapParallel(t *testing.T) { } generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) mapFunction := func(value interface{}) (interface{}, error) { stringValue := value.(string) @@ -39,7 +39,7 @@ func TestMapParallelHasError(t *testing.T) { inputSlice := []string{"DogCows", "goes", "Moof!", errorValue, "you", "like", "Clarus", "the", "DogCow?"} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) mapFunction := func(value interface{}) (interface{}, error) { stringValue := value.(string) @@ -60,7 +60,7 @@ func TestFilterParallel(t *testing.T) { inputSlice := []int{7, 4, 2, 3, 9, 5, 6, 0, 8, 1} expectedSlice := helper.InterfaceSlice([]int{7, 9, 6, 8}) generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) filterFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -80,7 +80,7 @@ func TestFilterParallelHasError(t *testing.T) { errorValue := 9 inputSlice := []int{7, 4, 2, 3, errorValue, 5, 6, 0, 8, 1} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) filterFunction := func(value interface{}) (bool, error) { intValue := value.(int) diff --git a/intermediate/link_chain_test.go b/link_chain_test.go similarity index 92% rename from intermediate/link_chain_test.go rename to link_chain_test.go index b472a8d..6c4a8ea 100644 --- a/intermediate/link_chain_test.go +++ b/link_chain_test.go @@ -1,4 +1,4 @@ -package intermediate +package rangechain import ( "errors" @@ -18,7 +18,7 @@ func TestMap(t *testing.T) { } generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) mapFunction := func(value interface{}) (interface{}, error) { stringValue := value.(string) @@ -42,7 +42,7 @@ func TestMapGeneratesError(t *testing.T) { } generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) mapFunction := func(value interface{}) (interface{}, error) { stringValue := value.(string) @@ -64,7 +64,7 @@ func TestFilter(t *testing.T) { inputSlice := []int{7, 4, 2, 3, 9, 5, 6, 0, 8, 1} expectedSlice := helper.InterfaceSlice([]int{7, 9, 6, 8}) generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) filterFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -84,7 +84,7 @@ func TestFilterHasError(t *testing.T) { expectedError := errors.New("an example error") inputSlice := []int{7, 4, 2, 3, errorValue, 5, 6, 0, 8, 1} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) filterFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -104,7 +104,7 @@ func TestSkip(t *testing.T) { inputSlice := []int{7, 4, 2, 3, 9, 5, 6, 0, 8, 1} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) howManyToSkip := 3 actualSlice, err := link.Skip(howManyToSkip).Slice() @@ -118,7 +118,7 @@ func TestSkipLargerThanSlice(t *testing.T) { inputSlice := []int{7, 4, 2, 3, 9, 5, 6, 0, 8, 1} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Skip(len(inputSlice) + 1).Slice() @@ -131,7 +131,7 @@ func TestLimit(t *testing.T) { inputSlice := []int{7, 4, 2, 3, 9, 5, 6, 0, 8, 1} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) howManyToKeep := 6 actualSlice, err := link.Limit(howManyToKeep).Slice() @@ -145,7 +145,7 @@ func TestLimitLargerThanSlice(t *testing.T) { inputSlice := []int{7, 4, 2, 3, 9, 5, 6, 0, 8, 1} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Limit(len(inputSlice) + 1).Slice() @@ -159,7 +159,7 @@ func TestDistinct(t *testing.T) { inputSlice := []int{7, 4, 2, 7, 3, 7, 9, 5, 5, 2, 6, 0, 8, 1} expectedSlice := helper.InterfaceSlice([]int{7, 4, 2, 3, 9, 5, 6, 0, 8, 1}) generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Distinct().Slice() @@ -173,7 +173,7 @@ func TestFlattenWithSliceOfSlice(t *testing.T) { inputSlice := [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} expectedSlice := helper.InterfaceSlice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9}) generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Flatten().Slice() @@ -187,7 +187,7 @@ func TestFlattenWithSliceMix(t *testing.T) { inputSlice := []interface{}{[]int{1, 2, 3}, 4, []int{7, 8, 9}} expectedSlice := helper.InterfaceSlice([]int{1, 2, 3, 4, 7, 8, 9}) generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Flatten().Slice() @@ -201,7 +201,7 @@ func TestFlattenWithArray(t *testing.T) { inputSlice := []interface{}{[...]int{1, 2, 3}, 4, [...]int{7, 8, 9}} expectedSlice := helper.InterfaceSlice([]int{1, 2, 3, 4, 7, 8, 9}) generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Flatten().Slice() @@ -212,13 +212,13 @@ func TestFlattenWithArray(t *testing.T) { func TestFlattenWithChannel(t *testing.T) { assert := assert.New(t) - firstChannel := createTestChannel([]int{1, 2, 3}) - secondChannel := createTestChannel([]int{7, 8, 9}) + firstChannel := createTestIntChannel([]int{1, 2, 3}) + secondChannel := createTestIntChannel([]int{7, 8, 9}) inputSlice := []interface{}{firstChannel, 4, secondChannel} expectedSlice := helper.InterfaceSlice([]int{1, 2, 3, 4, 7, 8, 9}) generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Flatten().Slice() @@ -257,7 +257,7 @@ func TestFlattenWithSliceAndMap(t *testing.T) { } generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Flatten().Slice() @@ -279,7 +279,7 @@ func TestSort(t *testing.T) { inputSlice := []int{7, 4, 2, 3, 9, 5, 6, 0, 8, 1} expectedSlice := helper.InterfaceSlice([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) returnLessFunction := func(sliceToSort []interface{}) func(int, int) bool { return func(i int, j int) bool { @@ -301,7 +301,7 @@ func TestSortHasError(t *testing.T) { errorValue := 9 inputSlice := []int{7, 4, 2, 3, errorValue, 5, 6, 0, 8, 1} generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) returnLessFunction := func(sliceToSort []interface{}) func(int, int) bool { return func(i int, j int) bool { @@ -321,7 +321,7 @@ func TestReverse(t *testing.T) { inputSlice := []int{7, 4, 2, 3, 9, 5, 6, 0, 8, 1} expectedSlice := helper.InterfaceSlice([]int{1, 8, 0, 6, 5, 9, 3, 2, 4, 7}) generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Reverse().Slice() @@ -336,14 +336,14 @@ func TestReverseHasError(t *testing.T) { errorValue := 9 inputSlice := []int{7, 4, 2, 3, errorValue, 5, 6, 0, 8, 1} generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) _, err := link.Reverse().Slice() assert.Equal(expectedError, err) } -func createTestChannel(intSlice []int) chan interface{} { +func createTestIntChannel(intSlice []int) chan interface{} { intChannel := make(chan interface{}) go func() { diff --git a/intermediate/link_termination.go b/link_termination.go similarity index 99% rename from intermediate/link_termination.go rename to link_termination.go index dde428b..e272634 100644 --- a/intermediate/link_termination.go +++ b/link_termination.go @@ -1,4 +1,4 @@ -package intermediate +package rangechain import ( "errors" diff --git a/intermediate/link_termination_test.go b/link_termination_test.go similarity index 93% rename from intermediate/link_termination_test.go rename to link_termination_test.go index 00e5530..3c704cb 100644 --- a/intermediate/link_termination_test.go +++ b/link_termination_test.go @@ -1,4 +1,4 @@ -package intermediate +package rangechain import ( @@ -14,7 +14,7 @@ func TestSlice(t *testing.T) { assert := assert.New(t) expectedSlice := []int{987, 8, 26} generation := generator.FromSlice(expectedSlice) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Slice() @@ -29,7 +29,7 @@ func TestSliceWithErrorReturnsPartOfSlice(t *testing.T) { inputSlice := []int{987, 8, errorValue} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) actualSlice, err := link.Slice() @@ -42,7 +42,7 @@ func TestChannel(t *testing.T) { expectedSlice := []int{987, 8, 26} generation := generator.FromSlice(expectedSlice) - link := NewLink(generation) + link := newLink(generation) var seenItems []interface{} valueChannel, errorChannel := link.Channel() @@ -62,7 +62,7 @@ func TestChannelHasError(t *testing.T) { inputSlice := []int{987, errorValue, 26} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) var seenItems []interface{} valueChannel, errorChannel := link.Channel() @@ -80,7 +80,7 @@ func TestForEach(t *testing.T) { inputSlice := []int{987, 8, 26} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) var seenItems []interface{} forEachFunction := func(value interface{}) { @@ -97,7 +97,7 @@ func TestForEachHasError(t *testing.T) { inputSlice := []int{987, errorValue, 26} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) forEachFunction := func(value interface{}) {} err := link.ForEach(forEachFunction) @@ -115,7 +115,7 @@ func TestForEachParallel(t *testing.T) { 8: true, } generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) seenItems := map[int]bool{} seenItemsLock := sync.RWMutex{} @@ -147,7 +147,7 @@ func TestForEachParallelHasError(t *testing.T) { inputSlice := []int{987, errorValue, 26} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) forEachFunction := func(value interface{}) {} err := link.ForEachParallel(forEachFunction) @@ -160,7 +160,7 @@ func TestCount(t *testing.T) { inputSlice := []int{987, 8, 26} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualCount, err := link.Count() @@ -175,7 +175,7 @@ func TestCountWithErrorStillCounts(t *testing.T) { inputSlice := []int{987, errorValue, errorValue} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) actualCount, err := link.Count() @@ -192,7 +192,7 @@ func TestCountWithFirstErrorReturns(t *testing.T) { expectedError := errors.New("an example error yo") secondError := errors.New("another error") generation := wrapGeneratorWithError(createGeneratorWithError(inputSlice, errorValue, expectedError), secondErrorValue, secondError) - link := NewLink(generation) + link := newLink(generation) _, err := link.Count() @@ -204,7 +204,7 @@ func TestFirst(t *testing.T) { inputSlice := []int{987, 8, 26} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualFirst, err := link.First() @@ -218,7 +218,7 @@ func TestFirstWithEmptySlice(t *testing.T) { var inputSlice []int generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualFirst, err := link.First() @@ -233,7 +233,7 @@ func TestFirstHasError(t *testing.T) { inputSlice := []int{errorValue, 8, 26} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) actualFirst, err := link.First() @@ -246,7 +246,7 @@ func TestLast(t *testing.T) { inputSlice := []int{987, 8, 26} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualLast, err := link.Last() @@ -260,7 +260,7 @@ func TestLastWithEmptySlice(t *testing.T) { var inputSlice []int generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) actualLast, err := link.Last() @@ -275,7 +275,7 @@ func TestLastHasError(t *testing.T) { inputSlice := []int{987, 8, errorValue} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) _, err := link.Last() @@ -287,7 +287,7 @@ func TestAllMatch(t *testing.T) { inputSlice := []int{984, 8, 26} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) allMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -304,7 +304,7 @@ func TestNotAllMatch(t *testing.T) { inputSlice := []int{984, 7, 26} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) allMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -321,7 +321,7 @@ func TestAllMatchWithEmptySlice(t *testing.T) { var inputSlice []int generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) allMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -340,7 +340,7 @@ func TestAllMatchWithEarlierError(t *testing.T) { inputSlice := []int{984, errorValue, 26} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) allMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -359,7 +359,7 @@ func TestAllMatchWithErrorInMatchFunction(t *testing.T) { inputSlice := []int{984, errorValue, 26} expectedError := errors.New("an example error yo") generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) allMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -379,7 +379,7 @@ func TestAnyMatch(t *testing.T) { inputSlice := []int{985, 3, 26} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) anyMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -396,7 +396,7 @@ func TestNotAnyMatch(t *testing.T) { inputSlice := []int{985, 7, 29} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) anyMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -413,7 +413,7 @@ func TestAnyMatchWithEmptySlice(t *testing.T) { var inputSlice []int generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) anyMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -432,7 +432,7 @@ func TestAnyMatchWithEarlierError(t *testing.T) { inputSlice := []int{985, 3, errorValue} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) anyMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -451,7 +451,7 @@ func TestAnyMatchWithErrorInMatchFunction(t *testing.T) { inputSlice := []int{985, 3, errorValue} expectedError := errors.New("an example error yo") generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) anyMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -471,7 +471,7 @@ func TestNoneMatch(t *testing.T) { inputSlice := []int{985, 3, 27} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) noneMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -488,7 +488,7 @@ func TestNotNoneMatch(t *testing.T) { inputSlice := []int{985, 7, 28} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) noneMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -505,7 +505,7 @@ func TestNoneMatchWithEmptySlice(t *testing.T) { var inputSlice []int generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) noneMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -524,7 +524,7 @@ func TestNoneMatchWithEarlierError(t *testing.T) { inputSlice := []int{985, errorValue, 27} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) noneMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -543,7 +543,7 @@ func TestNoneMatchWithErrorInMatchFunction(t *testing.T) { inputSlice := []int{985, errorValue, 27} expectedError := errors.New("an example error yo") generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) noneMatchFunction := func(value interface{}) (bool, error) { intValue := value.(int) @@ -564,7 +564,7 @@ func TestReduce(t *testing.T) { inputSlice := []int{987, 8, 26} expectedValue := inputSlice[0] * inputSlice[1] * inputSlice[2] generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) reduceFunction := func(firstItem interface{}, secondItem interface{}) (interface{}, error) { firstIntItem := firstItem.(int) @@ -584,7 +584,7 @@ func TestReduceWithOneItem(t *testing.T) { inputSlice := []int{987} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) reduceFunction := func(firstItem interface{}, secondItem interface{}) (interface{}, error) { firstIntItem := firstItem.(int) @@ -604,7 +604,7 @@ func TestReduceWithZeroItems(t *testing.T) { inputSlice := []int{} generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) reduceFunction := func(firstItem interface{}, secondItem interface{}) (interface{}, error) { firstIntItem := firstItem.(int) @@ -625,7 +625,7 @@ func TestReduceWithEarlierError(t *testing.T) { inputSlice := []int{987, 8, errorValue} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) reduceFunction := func(firstItem interface{}, secondItem interface{}) (interface{}, error) { firstIntItem := firstItem.(int) @@ -645,7 +645,7 @@ func TestReduceWithErrorInReduceFunction(t *testing.T) { inputSlice := []int{987, 8, errorValue} expectedError := errors.New("an example error yo") generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) reduceFunction := func(firstItem interface{}, secondItem interface{}) (interface{}, error) { firstIntItem := firstItem.(int) @@ -668,7 +668,7 @@ func TestReduceWithInitialValue(t *testing.T) { inputInitialValue := 4 expectedValue := inputInitialValue * inputSlice[0] * inputSlice[1] * inputSlice[2] generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) reduceFunction := func(firstItem interface{}, secondItem interface{}) (interface{}, error) { firstIntItem := firstItem.(int) @@ -688,7 +688,7 @@ func TestReduceWithInitialValueWithOneItem(t *testing.T) { inputSlice := []int{987} inputInitialValue := 4 generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) reduceFunction := func(firstItem interface{}, secondItem interface{}) (interface{}, error) { firstIntItem := firstItem.(int) @@ -708,7 +708,7 @@ func TestReduceWithInitialValueWithZeroItems(t *testing.T) { inputSlice := []int{} inputInitialValue := 4 generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) reduceFunction := func(firstItem interface{}, secondItem interface{}) (interface{}, error) { firstIntItem := firstItem.(int) @@ -729,7 +729,7 @@ func TestReduceWithInitialValueWithEarlierError(t *testing.T) { inputSlice := []int{987, errorValue, 26} expectedError := errors.New("an example error yo") generation := createGeneratorWithError(inputSlice, errorValue, expectedError) - link := NewLink(generation) + link := newLink(generation) reduceFunction := func(firstItem interface{}, secondItem interface{}) (interface{}, error) { firstIntItem := firstItem.(int) @@ -749,7 +749,7 @@ func TestReduceWithInitialValueWithErrorInReduceFunction(t *testing.T) { inputSlice := []int{987, errorValue, 26} expectedError := errors.New("an example error yo") generation := generator.FromSlice(inputSlice) - link := NewLink(generation) + link := newLink(generation) reduceFunction := func(firstItem interface{}, secondItem interface{}) (interface{}, error) { firstIntItem := firstItem.(int) From bcddfbb18e78ca9b9ace6e667341254ec83d4349 Mon Sep 17 00:00:00 2001 From: halprin Date: Sat, 30 Oct 2021 23:54:11 -0600 Subject: [PATCH 5/9] Update code documentation from removing intermediate package --- link.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/link.go b/link.go index 9400142..f5c98ed 100644 --- a/link.go +++ b/link.go @@ -1,6 +1,6 @@ package rangechain -// Link is not meant to be initialized directly by external users. Use the `From*` functions in the parent package rangechain. +// Link is not meant to be initialized directly by external users. Use the `From*` functions. type Link struct { generator func() (interface{}, error) } From fe46c9da3d498a3bed12f3763ffad477cc56f3ca Mon Sep 17 00:00:00 2001 From: halprin Date: Sun, 31 Oct 2021 16:18:07 -0600 Subject: [PATCH 6/9] Move the Tuple out of its private location to users are able to use it --- begin.go | 2 +- begin_test.go | 70 +++++++++++++++++++++++++++------ example_test.go | 14 +++---- internal/generator/generator.go | 14 ++----- internal/generator/keyvalue.go | 15 +++++++ keyvalue/interface.go | 7 ++++ link_chain.go | 2 +- link_chain_test.go | 14 +++---- 8 files changed, 101 insertions(+), 37 deletions(-) create mode 100644 internal/generator/keyvalue.go create mode 100644 keyvalue/interface.go diff --git a/begin.go b/begin.go index d4caf7c..a6750d7 100644 --- a/begin.go +++ b/begin.go @@ -32,7 +32,7 @@ func FromChannel(channel interface{}) *Link { } // FromMap starts the chain with the supplied map. -// Chaining and terminating methods can now be called on the result. The singular value used to represent the key and value pairs is `generator.MapTuple` of `github.com/halprin/rangechain/generator`. +// Chaining and terminating methods can now be called on the result. The singular value used to represent the key and value pairs is `keyvalue.KeyValuer` of `github.com/halprin/rangechain/keyvalue`. func FromMap(aMap interface{}) *Link { mapGenerator := generator.FromMap(aMap) diff --git a/begin_test.go b/begin_test.go index 98b3e73..ddec700 100644 --- a/begin_test.go +++ b/begin_test.go @@ -1,7 +1,7 @@ package rangechain import ( - "github.com/halprin/rangechain/internal/generator" + "github.com/halprin/rangechain/keyvalue" "github.com/stretchr/testify/assert" "testing" ) @@ -61,26 +61,39 @@ func TestFromMap(t *testing.T) { chain := FromMap(input) expectedOutput := []interface{}{ - generator.MapTuple{ - Key: key1, - Value: value1, + &testKeyValue{ + TheKey: key1, + TheValue: value1, }, - generator.MapTuple{ - Key: key2, - Value: value2, + &testKeyValue{ + TheKey: key2, + TheValue: value2, }, - generator.MapTuple{ - Key: key3, - Value: value3, + &testKeyValue{ + TheKey: key3, + TheValue: value3, }, } slice, err := chain.Slice() //not testing the order because we are not guaranteed the order in which a map is iterated over - assert.ElementsMatch(expectedOutput, slice) + assertEqualsBasedOnKeyValuerInterface(t, expectedOutput, slice) assert.Nil(err) } +type testKeyValue struct { + TheKey interface{} + TheValue interface{} +} + +func (t *testKeyValue) Key() interface{} { + return t.TheKey +} + +func (t *testKeyValue) Value() interface{} { + return t.TheValue +} + func createTestStringChannel(stringSlice []string) chan string { stringChannel := make(chan string) @@ -93,3 +106,38 @@ func createTestStringChannel(stringSlice []string) chan string { return stringChannel } + +func assertEqualsBasedOnKeyValuerInterface(t *testing.T, expected []interface{}, actual []interface{}) { + assert := assert.New(t) + + assert.Len(actual, len(expected)) + + for _, expectedValue := range expected { + expectedKeyValuer, isType := expectedValue.(keyvalue.KeyValuer) + if !isType { + continue + } + keyToFind := expectedKeyValuer.Key() + foundMatch := false + + for _, actualValue := range actual { + actualKeyValuer, isType := actualValue.(keyvalue.KeyValuer) + if !isType { + continue + } + actualKey := actualKeyValuer.Key() + + if actualKey != keyToFind { + continue + } + + if expectedKeyValuer.Value() != actualKeyValuer.Value() { + continue + } + + foundMatch = true + } + + assert.True(foundMatch) + } +} diff --git a/example_test.go b/example_test.go index a7febf6..d28a37e 100644 --- a/example_test.go +++ b/example_test.go @@ -2,7 +2,7 @@ package rangechain import ( "fmt" - "github.com/halprin/rangechain/internal/generator" + "github.com/halprin/rangechain/keyvalue" "testing" ) @@ -60,17 +60,17 @@ func TestSortingMaps(t *testing.T) { chain := FromMap(aMap) sortedAppleStuff, _ := chain.Sort(func(mapValuesToSort []interface{}) func(int, int) bool { return func(index1 int, index2 int) bool { - mapValue1 := mapValuesToSort[index1].(generator.MapTuple) - mapValue2 := mapValuesToSort[index2].(generator.MapTuple) + mapValue1 := mapValuesToSort[index1].(keyvalue.KeyValuer) + mapValue2 := mapValuesToSort[index2].(keyvalue.KeyValuer) - rating1 := mapValue1.Value.(int) - rating2 := mapValue2.Value.(int) + rating1 := mapValue1.Value().(int) + rating2 := mapValue2.Value().(int) return rating1 > rating2 } }).Map(func(value interface{}) (interface{}, error) { - mapValue := value.(generator.MapTuple) - return mapValue.Key, nil + mapValue := value.(keyvalue.KeyValuer) + return mapValue.Key(), nil }).Slice() fmt.Println(sortedAppleStuff) diff --git a/internal/generator/generator.go b/internal/generator/generator.go index 996ca0a..b429e44 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -10,12 +10,6 @@ import ( // Exhausted is returned as an expected error from the generators to designate an end of the generator. var Exhausted = errors.New("generator exhausted") -// MapTuple is used to represent the key and value pairs of a map when iterating over a map. -type MapTuple struct { - Key interface{} - Value interface{} -} - // FromSlice creates a generator for a slice. func FromSlice(slice interface{}) func() (interface{}, error) { if !helper.IsSlice(slice) { @@ -69,12 +63,12 @@ func FromMap(aMap interface{}) func() (interface{}, error) { return 0, Exhausted } - mapTuple := MapTuple{ - Key: mapIterator.Key().Interface(), - Value: mapIterator.Value().Interface(), + tuple := &mapTuple{ + TheKey: mapIterator.Key().Interface(), + TheValue: mapIterator.Value().Interface(), } - return mapTuple, nil + return tuple, nil } } diff --git a/internal/generator/keyvalue.go b/internal/generator/keyvalue.go new file mode 100644 index 0000000..e69e7af --- /dev/null +++ b/internal/generator/keyvalue.go @@ -0,0 +1,15 @@ +package generator + +// mapTuple implements the `keyvalue.KeyValuer` interface and is used when +type mapTuple struct { + TheKey interface{} + TheValue interface{} +} + +func (m *mapTuple) Key() interface{} { + return m.TheKey +} + +func (m *mapTuple) Value() interface{} { + return m.TheValue +} diff --git a/keyvalue/interface.go b/keyvalue/interface.go new file mode 100644 index 0000000..9466c2e --- /dev/null +++ b/keyvalue/interface.go @@ -0,0 +1,7 @@ +package keyvalue + +// KeyValuer is used to represent the key and value pairs. +type KeyValuer interface { + Key() interface{} + Value() interface{} +} diff --git a/link_chain.go b/link_chain.go index bb356bd..a81010d 100644 --- a/link_chain.go +++ b/link_chain.go @@ -97,7 +97,7 @@ func (receiver *Link) Distinct() *Link { return newLink(distinctGenerator) } -// Flatten will iterate over all the values in the chain, but any value encountered that is a range-able container itself will also have its values iterated over first before continuing with the remaining values in the chain. Maps flatten to its `generator.MapTuple` key and value pairs. +// Flatten will iterate over all the values in the chain, but any value encountered that is a range-able container itself will also have its values iterated over first before continuing with the remaining values in the chain. Maps flatten to its `generator.mapTuple` key and value pairs. func (receiver *Link) Flatten() *Link { var currentGenerator func() (interface{}, error) diff --git a/link_chain_test.go b/link_chain_test.go index 6c4a8ea..c555a2f 100644 --- a/link_chain_test.go +++ b/link_chain_test.go @@ -243,13 +243,13 @@ func TestFlattenWithSliceAndMap(t *testing.T) { 1, 2, 3, - generator.MapTuple{ - Key: key1, - Value: value1, + &testKeyValue{ + TheKey: key1, + TheValue: value1, }, - generator.MapTuple{ - Key: key2, - Value: value2, + &testKeyValue{ + TheKey: key2, + TheValue: value2, }, 7, 8, @@ -262,7 +262,7 @@ func TestFlattenWithSliceAndMap(t *testing.T) { actualSlice, err := link.Flatten().Slice() //not testing the order of the entire expected slice because we are not guaranteed the order in which a map is iterated over - assert.ElementsMatch(expectedSlice, actualSlice) + assertEqualsBasedOnKeyValuerInterface(t, expectedSlice, actualSlice) assert.Nil(err) //test the order for the non-map flattened parts assert.Equal(expectedSlice[0], actualSlice[0]) From 3bd7e2e43b80e658e7367a4dda0050c80caf5b3f Mon Sep 17 00:00:00 2001 From: halprin Date: Sun, 31 Oct 2021 16:37:37 -0600 Subject: [PATCH 7/9] Update documentation --- README.md | 4 ++-- keyvalue/interface.go | 3 ++- link_chain.go | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6559676..f8cd730 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ chain := rangechain.FromSlice(container) | `FromSlice` | • `slice` - A slice to be used to start the chain. | Starts the chain with the supplied slice. Chaining and terminating methods can now be called on the result. | | `FromArray` | • `array` - An array to be used to start the chain. | Starts the chain with the supplied array. Chaining and terminating methods can now be called on the result. | | `FromChannel` | • `channel` - A channel to be used to start the chain. | Starts the chain with the supplied channel. Chaining and terminating methods can now be called on the result. | -| `FromMap` | • `aMap` - A map to be used to start the chain. | Starts the chain with the supplied map. Chaining and terminating methods can now be called on the result. The singular value used to represent the key and value pairs is `generator.MapTuple` of `github.com/halprin/rangechain/generator`. | +| `FromMap` | • `aMap` - A map to be used to start the chain. | Starts the chain with the supplied map. Chaining and terminating methods can now be called on the result. The singular value used to represent the key and value pairs is `keyvalue.KeyValuer` of `github.com/halprin/rangechain/keyvalue`. | From there, one can call a plethora of additional methods to modify the container passed in originally. The methods are outlined below. The methods fall into one of two categories: chaining or terminating. @@ -76,7 +76,7 @@ terminating method is called. | `Skip` | Skips over the parameter `skipNumber` number of values and effectively removes them from the chain. Also skips over any errors previously generated. | | `Limit` | Stops the chain after the parameter `keepSize` number of values. Any elements afterward are effectively removed. | | `Distinct` | Removes any duplicates. | -| `Flatten` | Will iterate over all the values in the chain, but any value encountered that is a range-able container itself will also have its values iterated over first before continuing with the remaining values in the chain. Maps flatten to its `generator.MapTuple` key and value pairs. | +| `Flatten` | Will iterate over all the values in the chain, but any value encountered that is a range-able container itself will also have its values iterated over first before continuing with the remaining values in the chain. Maps flatten to its `keyvalue.KeyValuer` key and value pairs. | | `Sort` | Sorts the chain given the `Less` function returned from the `returnLessFunction` function parameter. The `returnLessFunction` function is called with the entire serialized chain as a slice and _returns_ a function that satisfies the same requirements as the [Interface type's](https://pkg.go.dev/sort#Interface) `Less` function. See the [`TestSortingMaps` example](./example_test.go). This method is expensive because it must serialize all the values into a slice first. | | `Reverse` | Reverses the order of the chain. The last item will be first, and the first item will be last. This method is expensive because it must serialize all the values into a slice first. | diff --git a/keyvalue/interface.go b/keyvalue/interface.go index 9466c2e..e3113a7 100644 --- a/keyvalue/interface.go +++ b/keyvalue/interface.go @@ -1,6 +1,7 @@ +// Package keyvalue exists to specify the interface of `KeyValuer`. package keyvalue -// KeyValuer is used to represent the key and value pairs. +// KeyValuer is used to represent key and value pairs. type KeyValuer interface { Key() interface{} Value() interface{} diff --git a/link_chain.go b/link_chain.go index a81010d..8ed0a6e 100644 --- a/link_chain.go +++ b/link_chain.go @@ -97,7 +97,7 @@ func (receiver *Link) Distinct() *Link { return newLink(distinctGenerator) } -// Flatten will iterate over all the values in the chain, but any value encountered that is a range-able container itself will also have its values iterated over first before continuing with the remaining values in the chain. Maps flatten to its `generator.mapTuple` key and value pairs. +// Flatten will iterate over all the values in the chain, but any value encountered that is a range-able container itself will also have its values iterated over first before continuing with the remaining values in the chain. Maps flatten to its `keyvalue.KeyValuer` key and value pairs. func (receiver *Link) Flatten() *Link { var currentGenerator func() (interface{}, error) From 4b851967ee5da1bff070a9c5b77d13a03e687036 Mon Sep 17 00:00:00 2001 From: halprin Date: Sun, 31 Oct 2021 16:47:28 -0600 Subject: [PATCH 8/9] Uncomment unneeded comment --- link.go | 1 - 1 file changed, 1 deletion(-) diff --git a/link.go b/link.go index f5c98ed..a07c712 100644 --- a/link.go +++ b/link.go @@ -5,7 +5,6 @@ type Link struct { generator func() (interface{}, error) } -// newLink is not meant to be called directly by external users. Use the `From*` functions in the parent package rangechain. func newLink(generator func() (interface{}, error)) *Link { return &Link{ generator: generator, From 8f96a6e45630c10d46b98e8308714490d3bb9175 Mon Sep 17 00:00:00 2001 From: halprin Date: Mon, 22 Nov 2021 19:52:23 -0700 Subject: [PATCH 9/9] Update comment --- internal/generator/keyvalue.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/generator/keyvalue.go b/internal/generator/keyvalue.go index e69e7af..0ac5557 100644 --- a/internal/generator/keyvalue.go +++ b/internal/generator/keyvalue.go @@ -1,6 +1,6 @@ package generator -// mapTuple implements the `keyvalue.KeyValuer` interface and is used when +// mapTuple implements the `keyvalue.KeyValuer` interface and is used to represent map's keys and values type mapTuple struct { TheKey interface{} TheValue interface{}