Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add slices reduce functions #67

Merged
merged 3 commits into from
Oct 8, 2024
Merged

Add slices reduce functions #67

merged 3 commits into from
Oct 8, 2024

Conversation

Sypheos
Copy link
Member

@Sypheos Sypheos commented Oct 3, 2024

What does this PR do?

Add reduce function from zero or with base

What are the observable changes?

Sum helper

Good PR checklist

  • Title makes sense
  • Is against the correct branch
  • Only addresses one issue
  • Properly assigned
  • Added/updated tests
  • Added/updated documentation
  • Properly labeled

@Sypheos Sypheos self-assigned this Oct 3, 2024
@Sypheos Sypheos requested a review from a team as a code owner October 3, 2024 16:15
@Sypheos Sypheos requested review from DarkMiMolle and xgoffin and removed request for a team October 3, 2024 16:15
slices/reduce.go Outdated
constraints.Integer | constraints.Float | ~string
}

func Sum[T sumable](i, j T) T {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func Sum[T sumable](i, j T) T {
func Sum[T sumable](vs ...T) T {

you could generalize it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func Sum[T sumable](i, j T) T {
func Sum[T sumable](values ...T) T {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That won't compile unless the reduce function accepts variadic args too, which kind of defeats the purpose of a reduce.

We could change things up and have Sum call Reduce which will provides a function link sum := slices.Sum(numbers)

slices/reduce.go Outdated

import "golang.org/x/exp/constraints"

func ReduceWith[S ~[]E, E any, A any](s S, acc A, fn func(A, E) A) A {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im skeptical of the With, it does not evoke anything to me, wdyt of ReduceFrom or ReduceWithInitial

Copy link
Contributor

@xgoffin xgoffin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, as said, I'm not big on this change. I think reductions not only damage code readability, but that in the cases where they need to happen, they can be made on a case-by-case basis without having to have a custom func for that. It's definitely a part of ruby I'm glad we don't have in go, so I don't really wanna bring it in ourselves 😅

slices/reduce.go Outdated

import "golang.org/x/exp/constraints"

func ReduceWith[S ~[]E, E any, A any](s S, acc A, fn func(A, E) A) A {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReduceWithAggregator?

Also is this not possible?

Suggested change
func ReduceWith[S ~[]E, E any, A any](s S, acc A, fn func(A, E) A) A {
func ReduceWith[E any, A any](s []E, acc A, fn func(A, E) A) A {

Not sure if the compiler'll like it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also naming the vars something a bit more explicit can be useful

  • s => elements
  • acc => accumulator
  • fn => transformationFunc
    Or something? Otherwise we're really sending a telegram like we do in ruby

Copy link
Member

@AlexisMontagne AlexisMontagne Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what @Sypheos wrote is pretty standard, it allows typedef of slices to be accepted as paramenter,

for some reason you'd like:

type Strings []string

you could pass directly a value of type Strings as first param

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • s => elements
  • acc => accumulator
  • fn => transformationFunc

I would go with something like:

  • s => slice
  • acc could stay the same, it is a pretty standard name for accumulators
  • fn => reduceFunc

slices/reduce.go Outdated
return acc
}

func Reduce[S ~[]E, E any, A any](s S, fn func(A, E) A) A {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly at this point, the heavy part of the API, to me, is the generic types. I think we can consider that the devs can pass the zero-value as accumulator themselves, don't you think? 🙂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both approaches are valid. We chose to have two functions to be more explicit, as opposed to Ruby, and avoid having to type out empty strut types.

slices/reduce.go Outdated
return ReduceWith(s, acc, fn)
}

type sumable interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will that not cause an issue? The fact that we have a private constraint on a publicly exposed func?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't bother the compiler since it is used as a constraint not as a value.

@Sypheos
Copy link
Member Author

Sypheos commented Oct 7, 2024

Eh, as said, I'm not big on this change. I think reductions not only damage code readability, but that in the cases where they need to happen, they can be made on a case-by-case basis without having to have a custom func for that. It's definitely a part of ruby I'm glad we don't have in go, so I don't really wanna bring it in ourselves 😅

We thought about using this helper in the PRs last sprint. It could actually have saved us some time, lines of code and believe it or not readability. We are not taking this out of Ruby but out of the Functional Programming book which IMO is a good thing.
If you think back, the same argument could have been done for the Map functions but I believe everyone is quite like it now. We also have the compiler and type enforcing in go that should avoid pondering what the output of the reduce and what signature to use.

@Sypheos Sypheos merged commit eea9ca5 into master Oct 8, 2024
2 checks passed
@Sypheos Sypheos deleted the sp/slices-reduce branch October 8, 2024 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants