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

feat: add Compose and Pipe functions #325

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

GCrispino
Copy link

Hello!

This PR adds functions Compose and Pipe (which is requested in #299), that respectively compose two functions and pipes the application of two functions.
These are common functions in utility libraries such as Ramda and Lodash.

Something worth noting is that these functions receive just two functions as arguments, which is not exactly what happens in their counterparts in Ramda/Lodash, where you can pass a variadic number of functions. I think this couldn't be replicated in Golang in a type safe way, but something like the PartialN functions and create ComposeN and PipeN functions.

A way to mitigate this is to create counterpart functions for different sizes of arguments, like Compose3/Pipe3 for composing/piping three functions, Compose4/Pipe4 for four functions, and so on.

PS: I know that the repo's README mentions that for contributing, one should talk with @samuelberthe on twitter. I tried doing so and got no response, so I decided to create this here anyway since there's an issue for something similar to this PR's contribution (#299). My apologies if this is not desired, but if this is not of the interest of the maintainers, no worries at all :)

@effinsky
Copy link

I'd say this definitely needs to be tested with some more complex scenarios, prepared to chain more than just 2 funcs, and work with other generic funcs from the lo lib.

@GCrispino
Copy link
Author

@effinsky do you have any more complex scenarios or generic functions from the library that would be good to test in mind?

As per chaining more than just 2 functions, I believe it's just a matter of creating additional functions that do the same with more arguments, or am I wrong? I added a new commit with definitions for Compose3 and Pipe3, which do the same as Compose and Pipe but supporting 3 functions as arguments. Is it what you're thinking about?

@effinsky
Copy link

I think when you're doing data ops like this you don't know exactly how many there might be, so it'd be cool to be able to chain as many as you want without swapping out the funcs. So maybe accept a varargs list of them? Then the problem is signatures, isn't it? Since the sig for a filter and for a map will be different, and with a generics impl as inflexible as it is with Go, that might be a problem. That said, there's stuff I'm surely not seeing and so maybe that's possible!

@GCrispino
Copy link
Author

GCrispino commented Mar 14, 2023

Then the problem is signatures, isn't it?

@effinsky exactly, you can't accept variadic type parameters in Golang (at least not yet). That's probably why this library has functions Partial1, Partial2, Partial3, and so on, for example, instead of having a single one that would accept variadic type parameters.

@effinsky
Copy link

Then the problem is signatures, isn't it?

@effinsky exactly, you can't accept variadic type parameters in Golang (at least not yet). That's probably why this library has functions Partial1, Partial2, Partial3, and so on, for example, instead of having a single one that would accept variadic type parameters.

We could accept a slice of funcs, I think, but then it'd be an issue of typing them so that all the sigs can fit in that general payload type.

Actually, tbh, I think having a pipe/compose that takes 3-5 fns is already enough for the vast majority of pipelines you might want. I don't think a mile-long pipeline would even be readable, unless we're taking very small ops, in which case they just look clear and neat.

All this said, I'm not sure if wouldn't be better to go with a 'chain' approach that lodash has -- this accepts a bunch of fns, and when u call 'value' on the return of the last one, it calls then and probably can do some nice lazy-eval optimizations. This'd be sweet, since potentially you wouldn't have to iterate over a collection EVERY TIME you call a higher order function on it.

@GCrispino
Copy link
Author

We could accept a slice of funcs, I think, but then it'd be an issue of typing them so that all the sigs can fit in that general payload type.

Yeah.

Actually, tbh, I think having a pipe/compose that takes 3-5 fns is already enough for the vast majority of pipelines you might want. I don't think a mile-long pipeline would even be readable, unless we're taking very small ops, in which case they just look clear and neat.

Agreed 👍🏼

All this said, I'm not sure if wouldn't be better to go with a 'chain' approach that lodash has -- this accepts a bunch of fns, and when u call 'value' on the return of the last one, it calls then and probably can do some nice lazy-eval optimizations. This'd be sweet, since potentially you wouldn't have to iterate over a collection EVERY TIME you call a higher order function on it.

Yeah, haven't thought too much about this. It might boil down to what's most comfortable to use and what not. Just thought it would be nice to have compose in this library since it's a very well known functional primitive 😄

@oybek oybek mentioned this pull request Sep 7, 2023
@sunjayaali
Copy link

#395

Hi all,

I created a PR similar to this feature with more flexibility of the arguments

@GCrispino GCrispino mentioned this pull request Aug 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants