Skip to content

Commit

Permalink
Span (#81)
Browse files Browse the repository at this point in the history
* WIP - branch switch

* Add span function

* Use named returns

* Improve branching on function

* Re-build to remove leftover comments
  • Loading branch information
xcgpseud authored and DylanMeeus committed Oct 25, 2019
1 parent fb82c56 commit f762872
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ These functions can be generated for every type.
| `Product` | `[a] -> a` || | | Returns the product of all elements in the slice.|
| `Reverse` | `[a] -> [a]` |||| Returns a slice with the elements reversed|
| `Sort` | `[a] -> [a]` ||| | Returns a sorted slice (original remains unsorted)|
| `Span` | `(a -> bool) -> [a] -> ([a], [a])`|||| Returns a tuple of all elements until the first one that does not match the predicate, followed by the remaining elements. |
| `Sum` | `[a] -> a` |||| The sum of elements in the slice|
| `Tail` | `[a] -> [a]` |||| Returns all elements minus the first|
| `Take` | `[a] -> uint64 -> [a]` |||| Take N elements from the slice, or all if N exceeds the length.|
Expand Down
1 change: 1 addition & 0 deletions functions/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ var (
"product.go": {ForNumbers},
"reverse.go": {ForNumbers, ForStrings, ForStructs},
"sort.go": {ForNumbers, ForStrings},
"span.go": {ForNumbers, ForStrings, ForStructs},
"sum.go": {ForNumbers, ForStrings},
"tail.go": {ForNumbers, ForStrings, ForStructs},
"take.go": {ForNumbers, ForStrings, ForStructs},
Expand Down
23 changes: 23 additions & 0 deletions functions/span.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package functions

// Span returns a tuple of any elements that satisfy the predicate up until the first failure, followed by
// the rest of the elements.
// Can be generated for any type.
func (s SliceType) Span(f func(ElementType) bool) (before SliceType, after SliceType) {
if f == nil {
return before, s
}

failed := false

for _, v := range s {
if failed || !f(v) {
after = append(after, v)
failed = true
} else {
before = append(before, v)
}
}

return
}
24 changes: 24 additions & 0 deletions template.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions types/Ints_hasgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,30 @@ func (s Ints) Sort() Ints {
return out
}

// =============== span.go =================

// Span returns a tuple of any elements that satisfy the predicate up until the first failure, followed by
// the rest of the elements.
// Can be generated for any type.
func (s Ints) Span(f func(int64) bool) (before Ints, after Ints) {
if f == nil {
return before, s
}

failed := false

for _, v := range s {
if failed || !f(v) {
after = append(after, v)
failed = true
} else {
before = append(before, v)
}
}

return
}

// =============== sum.go =================

// Sum returns the sum of all elements in the slice.
Expand Down
49 changes: 49 additions & 0 deletions types/Ints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,44 @@ var (
},
}

intsSpanTests = []struct {
input Ints
spanfunc func(int64) bool
before Ints
after Ints
}{
{
nil,
func(i int64) bool { return i < 3 },
Ints{},
Ints{},
},
{
Ints{1, 2, 3, 4, 5},
nil,
Ints{},
Ints{1, 2, 3, 4, 5},
},
{
Ints{1, 2, 3, 4, 5},
func(i int64) bool { return i < 9 },
Ints{1, 2, 3, 4, 5},
Ints{},
},
{
Ints{1, 2, 3, 4, 5},
func(i int64) bool { return i > 9 },
Ints{},
Ints{1, 2, 3, 4, 5},
},
{
Ints{1, 2, 3, 4, 5},
func(i int64) bool { return i < 3 },
Ints{1, 2},
Ints{3, 4, 5},
},
}

intsDropWhileTests = []struct {
input Ints
dropfunc func(int64) bool
Expand Down Expand Up @@ -1009,6 +1047,17 @@ func Test_IntsDrop(t *testing.T) {
}
}

func Test_IntsSpan(t *testing.T) {
for _, test := range intsSpanTests {
t.Run("", func(t *testing.T) {
before, after := test.input.Span(test.spanfunc)
if !test.before.Equals(before) || !test.after.Equals(after) {
t.Errorf("expected (%v, %v) but got (%v, %v)", test.before, test.after, before, after)
}
})
}
}

func Test_IntsDropWhile(t *testing.T) {
for _, test := range intsDropWhileTests {
t.Run("", func(t *testing.T) {
Expand Down
49 changes: 49 additions & 0 deletions types/Persons_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,44 @@ var (
},
}

structSpanTests = []struct {
input persons
spanfunc func(person) bool
before persons
after persons
}{
{
nil,
func(p person) bool { return p.age < 27 },
persons{},
persons{},
},
{
persons{dylan, ana, sean, tom, chris},
nil,
persons{},
persons{dylan, ana, sean, tom, chris},
},
{
persons{dylan, ana, sean, tom, chris},
func(p person) bool { return p.age < 100 },
persons{dylan, ana, sean, tom, chris},
persons{},
},
{
persons{dylan, ana, sean, tom, chris},
func(p person) bool { return p.age > 100 },
persons{},
persons{dylan, ana, sean, tom, chris},
},
{
persons{dylan, ana, sean, tom, chris},
func(p person) bool { return p.age < 27 },
persons{dylan},
persons{ana, sean, tom, chris},
},
}

structDropWhileTests = []struct {
input persons
dropfunc func(person) bool
Expand Down Expand Up @@ -710,6 +748,17 @@ func Test_structDrop(t *testing.T) {
}
}

func Test_structSpan(t *testing.T) {
for _, test := range structSpanTests {
t.Run("", func(t *testing.T) {
before, after := test.input.Span(test.spanfunc)
if !test.before.Equals(before) || !test.after.Equals(after) {
t.Errorf("expected (%v, %v) but got (%v, %v)", test.before, test.after, before, after)
}
})
}
}

func Test_structDropWhile(t *testing.T) {
for _, test := range structDropWhileTests {
t.Run("", func(t *testing.T) {
Expand Down
24 changes: 24 additions & 0 deletions types/Strings_hasgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,30 @@ func (s Strings) Sort() Strings {
return out
}

// =============== span.go =================

// Span returns a tuple of any elements that satisfy the predicate up until the first failure, followed by
// the rest of the elements.
// Can be generated for any type.
func (s Strings) Span(f func(string) bool) (before Strings, after Strings) {
if f == nil {
return before, s
}

failed := false

for _, v := range s {
if failed || !f(v) {
after = append(after, v)
failed = true
} else {
before = append(before, v)
}
}

return
}

// =============== sum.go =================

// Sum returns the sum of all elements in the slice.
Expand Down
49 changes: 49 additions & 0 deletions types/Strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,44 @@ var (
},
}

stringsSpanTests = []struct {
input Strings
spanfunc func(string) bool
before Strings
after Strings
}{
{
nil,
func(s string) bool { return len(s) < 3 },
Strings{},
Strings{},
},
{
Strings{"ABC", "ABCD", "ABCDE", "ABCDEF"},
nil,
Strings{},
Strings{"ABC", "ABCD", "ABCDE", "ABCDEF"},
},
{
Strings{"ABC", "ABCD", "ABCDE", "ABCDEF"},
func(s string) bool { return len(s) < 9 },
Strings{"ABC", "ABCD", "ABCDE", "ABCDEF"},
Strings{},
},
{
Strings{"ABC", "ABCD", "ABCDE", "ABCDEF"},
func(s string) bool { return len(s) > 9 },
Strings{},
Strings{"ABC", "ABCD", "ABCDE", "ABCDEF"},
},
{
Strings{"ABC", "ABCD", "ABCDE", "ABCDEF"},
func(s string) bool { return len(s) < 5 },
Strings{"ABC", "ABCD"},
Strings{"ABCDE", "ABCDEF"},
},
}

stringsDropWhileTests = []struct {
input Strings
dropfunc func(string) bool
Expand Down Expand Up @@ -888,6 +926,17 @@ func Test_StringsDrop(t *testing.T) {
}
}

func Test_StringsSpan(t *testing.T) {
for _, test := range stringsSpanTests {
t.Run("", func(t *testing.T) {
before, after := test.input.Span(test.spanfunc)
if !test.before.Equals(before) || !test.after.Equals(after) {
t.Errorf("expected (%v, %v) but got (%v, %v)", test.before, test.after, before, after)
}
})
}
}

func Test_StringsDropWhile(t *testing.T) {
for _, test := range stringsDropWhileTests {
t.Run("", func(t *testing.T) {
Expand Down
24 changes: 24 additions & 0 deletions types/persons_hasgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,30 @@ func (s persons) Reverse() (out persons) {
return
}

// =============== span.go =================

// Span returns a tuple of any elements that satisfy the predicate up until the first failure, followed by
// the rest of the elements.
// Can be generated for any type.
func (s persons) Span(f func(person) bool) (before persons, after persons) {
if f == nil {
return before, s
}

failed := false

for _, v := range s {
if failed || !f(v) {
after = append(after, v)
failed = true
} else {
before = append(before, v)
}
}

return
}

// =============== tail.go =================

// Tail takes [1 -> n] elements from a slice, where n = len(list)
Expand Down

0 comments on commit f762872

Please sign in to comment.