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

Feature Request: Functional API (wrapper around the OOP API) #1268

Closed
joshburgess opened this issue Jul 12, 2017 · 14 comments
Closed

Feature Request: Functional API (wrapper around the OOP API) #1268

joshburgess opened this issue Jul 12, 2017 · 14 comments

Comments

@joshburgess
Copy link
Contributor

joshburgess commented Jul 12, 2017

I realize this was discussed a few years ago, but there's still no functional API. Is there any way we could revive discussion about this?

It's the most painful thing about using Immutable.js for me. I realize the decision to use an OOP API was made in order to be more like native JS, and, therefore, easier for people to get into, but it's a real problem, because it gets in the way of using pipe/compose, currying, partial application, etc.... It becomes a barrier to introducing teammates to those concepts, because there's a major conflict between Immutable & those techniques. So, if they are unfamiliar with currying, for example, but are already using Immutable, it becomes really difficult to sell them on the idea at all.

Ramda & lodash/fp are quite popular nowadays, and more people than ever before are using FP techniques when writing JavaScript now. There seems to be an initiative at Facebook to guide the JS community further into FP (look at what's going on with Reason), but not offering a functional API for a very popular library gets in the way of this for people who are entrenched in the React/Redux/Immutable/etc. world already.

I realize that this wrapper could be created by a 3rd party, but it makes so much more sense to include it as an optional API directly in Immutable, because it would help expose more people to currying, composition, partial application, etc.... They would have less fear of learning new concepts, because they would see a major, popular, Facebook-affiliated library offering an API that encourages the use of them.

There's a real opportunity here, as there aren't many alternatives out there. Mori, for example, is not maintained. It's not kept up to date with updates to ClojureScript. The only other options out there are relatively obscure/unknown to most people.

I'm not even asking for an auto-curried API (although that would be nice). We could do that on the app side. Just having functional wrappers for the data structure methods would be good enough.

Thoughts?

@ariesshrimp
Copy link

ariesshrimp commented Jul 21, 2017

What are the costs? Potentially increased maintenance penalties, as changes to the core library must be propagated to the functional API?

But the core library itself seems to have stabilized profoundly. Almost all major development happened three years ago according to the GitHub commit graph:

GitHub commit graph shows an enormous spike in 2014, then mostly flat

The incompatibility between Immutable.js and Ramda is one of the most frequent complaints I hear about both libraries today, but an fp composable API for Immutable would address that directly.

I don't know how tall an ask this is, but recompose did basically this exact thing for the entire React API and more. Could the work be modeled off of that?

@joshburgess
Copy link
Contributor Author

joshburgess commented Jul 21, 2017

@joefraley Other projects that could be looked at as examples are lodash/fp, which was pretty much created in response to Ramda pulling away some Lodash users, and most (similar to RxJS, but more minimal & features a functional API alongside the method based API, in order to support programming in a pointfree style). There are also others, like fp-ts, an ADT library written in TypeScript, and collectable, one of the newer/lesser known persistent data structures libraries I mentioned that most people aren't aware of.

You're right that React users who also happen to be Ramda users are probably a large portion of the people wanting this, but it's not only about Ramda. In my experience, people who get used to frequently using currying & a pointfree style just don't want to go back to a strictly method chaining/fluent style at all, because it takes away a ton of flexibility. You simply just can't get the same level of function reuse. I often choose libraries now (at least, partially) based on whether or not they offer a pointfree-compatible API. It's one of the reasons I prefer Most over RxJS. I'll even write wrapper functions for native methods when I need to use them, just so that they don't get in the way when using composition.

But when working in more conservative environments where people have already bought heavily into using Immutable, it becomes really difficult to get buy-in... because, often, people who aren't familiar with that style are skeptical about its merits due to not seeing popular Facebook projects (like Immutable) supporting it.

That's why I think it's important to have it directly in Immutable as an optional API... or at least still under the Facebook umbrella organization if it were a separate repo. I'd be willing to help work on this, and will help create it as a separate, unaffiliated, standalone library if that's the only way, but that would really hurt its chances at popularity & acceptance for a lot of people at their day jobs. It would be much easier to talk managers/project leads/lead devs/etc. into it if they saw it as an "officially supported" way to use the library.

@ariesshrimp
Copy link

ariesshrimp commented Jul 23, 2017

@joshburgess: i'd also be happy to help. what are your thoughts on forking the wrapper with the aim of folding it back in to the main later on?

it feels like many of the major facebook driven oss libs have spotty interactions with the core team these days. for example, the flow repo has at least 10 open issues that orbit the same serious problem, but i haven't seen any core member participation in planning a solution.

it might be easier for this idea to find purchase if it's more realized already?

maybe the right starting point is to outline what's left of the pitch here. for example:

  1. Document the desired API with several examples (so that others can have a voice in its shape)
  2. Outline a strategy for the needed work (so that others can help estimate the difficulty/consequences)
  3. Break that outline into some tasks (so that the work can be easily divided)
  4. Define a happy path to acceptance of the new API (does it all go into the main lib in one PR? how complete does it need to be? how should it be accessible to end users? as a separate installation? as a special import?)

@leebyron
Copy link
Collaborator

Thanks for setting out a clear plan, @joefraley - @joshburgess if you're interested in pursuing this, I recommend following along that plan.

Ideally whatever change is introduced will be zero-cost to the overall filesize of this library. Perhaps that means a companion library for those seeking a FP API?

@ariesshrimp
Copy link

ariesshrimp commented Oct 2, 2017

@leebyron that makes sense. the only possible way to avoid adding size to immutable.js is to avoid adding any code. there's no way to offer a point-free API on top of the method chaining API without adding code. if we're not allowed to increase file-size at all, then at best we're talking about shipping a separate import.

this could look similar to react-dom, which exports renderToString from react-dom/server, so that people using only react-dom don't see that bundle increase. naming that export would be a challenge of the proposed API.

i wonder if a separate import would have the effect i hear @joshburgess craving. namely, if the point-free API is behind a secret passcode, then i wonder how it will reach the developers josh describes, who look to the main documentation of popular projects as a source of truth for best-and-even-acceptable-practices.

and now that i've said it, even if we were allowed to increase the bundle size, i wonder what kind of effort would meet that need? what i'm hearing josh say is that it's as much about publicity/endorsement of different paradigms as it is the possibility of their use. after all, other libraries have made point-free immutable data-structures their whole deal already.

alternatively, we could be talking about a hypothetical release of immutable that trades the method chaining API for a point-free one. i wouldn't expect that to be popular today, but i would be interested in hearing the merits/costs of that implementation. it might involve a careful discussion of who immutable's users are, and what their needs are. i'd expect that to lead directly into a conversation about how we know who they are and what their needs are, and how much anyone cares.

@ariesshrimp
Copy link

ariesshrimp commented Oct 2, 2017

at least writing a separate import would be easily promoted to the main package in a later release, so i guess that's the correct starting point no matter what. but that leaves the first question about whether that would do what josh wants it to do, and whether it would be worth the work, given that other excellent libraries already exist to fill the same void.

@joshburgess
Copy link
Contributor Author

If no file size increase is allowed, perhaps a sister library called immutable-fp (like lodash/fp?) that imports immutable internally and exposes a functional/pointfree-friendly style API might be the simplest solution? Then, it could be seen as an optional add-on for people willing to eat the cost of whatever extra filesize it has, while others could just keep using the original immutable library.

Or maybe we could work something out with tree shaking in one library?

@ariesshrimp
Copy link

ariesshrimp commented Oct 2, 2017

@joshburgess i like the separate library idea, but do you think such a library would fulfill your goals of exposing the immutable user community to point-free functional paradigms? i'm trying to imagine your target beneficiary.

i can only speak from personal experience. when i've worked in code-bases using immutable, on teams unfamiliar with point-free API's, it would not have been any easier for me to start using immutable-fp than it would have been to start using mori. the perceived burden of competing API's/paradigms creates the real impedance.

i can see how the official immutable docs/community blessing an fp API would be very influential in such a discussion. for example, the react-router community's transition to the v4 api has forced a lot of interesting design discussions into the open. no matter how much i preferred that approach, it wouldn't have found purchase on my team if it had been react-router/components@1 instead of react-router@4.

here's another way of drilling down into this question of "who's it for...?"

am i a happy immutable user today? then what would it take to convince me to try immutable/fp?

am i an unhappy immutable user today? then why would i prefer immutable/fp to mori?

is the imagined beneficiary this person: someone who wants to use immutable, but also wants to maintain their point-free, composition, fp sanctuary? if so, what is it about immutable that they find attractive, when other libraries might already meet their needs?

i'd love to hear more about your ideas, but here's what i think i'm hearing in this feature request: you see people in the js community looking at popular libraries (like immutable) for architectural guidance. you think it would be great if those libraries started using their influence to motivate paradigms you like (such as composability/fp strategies). so this feature request is really about using immutable as a platform to advocate for specific engineering principles.

i'm perfectly happy with that idea, i just want to be clear about the goal. i don't see any reason for immutable's maintainers to object to that, if it's zero cost to them and gives their users more options (that's what i hear @leebyron saying).

what i'm unclear on is how effective an immutable alternative will be at that more political end. it feels like what's really needed, to that end, is an immutable rebranding. what i'd like to be clear about is whether this project is simply the first step toward that. if not, i think i'm confused about how valuable this idea is, because i'm having a hard time picturing the people that would really benefit a lot from it.

@joshburgess
Copy link
Contributor Author

joshburgess commented Oct 3, 2017

@joefraley I think immutable-fp would only fulfill those goals if it lived under the facebook github organization and was mentioned in the immutable-js documentation. Otherwise, no, it would be ignored by most people. Many developers are very conservative when it comes to technology choices and are only willing to buy in to what large tech companies are doing.

I'd prefer it be an option within the same package/repo, if possible, obviously, but that's not up to me in the end. This is what lodash/fp does.

I'm not necessarily looking for FB orimmutable to specifically promote the functional style API. I just want it made available as an official option so that it's easier to get buy in on it and so that it can more easily fit into codebases already using ramda, sanctuary, lodash/fp, etc....

It could also live in the same repository here, but be published as a separate package on npm. I suppose that's a decent compromise?

@leebyron
Copy link
Collaborator

leebyron commented Oct 3, 2017

the only possible way to avoid adding size to immutable.js is to avoid adding any code. there's no way to offer a point-free API on top of the method chaining API without adding code. if we're not allowed to increase file-size at all, then at best we're talking about shipping a separate import.

This isn't a hard constraint, but people are already sensitive to the file size of this library. Obviously new additions will have some effect on size, but what I'd like to avoid is a 2x effect on the API surface area that results in a significant uptick in filesize as well.

There have also been requests for a more modular approach to this library in general, so I see shipping a separate import as directly inline with that goal. I like your parallel to react and react-dom - that's a great example of this.

i can only speak from personal experience. when i've worked in code-bases using immutable, on teams unfamiliar with point-free API's, it would not have been any easier for me to start using immutable-fp than it would have been to start using mori. the perceived burden of competing API's/paradigms creates the real impedance.

This I think gets to the heart of the issue. My other concern with including a FP style API directly in this library is that it requires API to describe two different ways to do each thing, and the impedance mismatch created by that would only add to the learning curve to adopting immutable collections.

I think immutable-fp would only fulfill those goals if it lived under the facebook github organization and was mentioned in the immutable-js documentation. Otherwise, no, it would be ignored by most people. Many developers are very conservative when it comes to technology choices and are only willing to buy in to what large tech companies are doing.

I would not be willing to change the immutable-js docs to favor a FP style over the existing OOP style. There's also no demand internally at Facebook for a FP style API over an OOP style API. I think you're right that many developers follow along with what large tech companies are doing, but it would be disingenuous for me to advocate for people to use an FP style API when that's not how we actually use Immutable.js ourselves.

In my experience, developers who are new to many of these concepts are far more likely to reject the whole set of ideas if introduced all at once. I don't think the FP style API is objectively better or worse than the OOP style API, but just presents a different set of tradeoffs and each may be more familiar to different developers. Ultimately, the vast majority of JavaScript developers are more familiar with OOP, which is why this library starts there.


I'm absolutely in support of FP style APIs, but I'd like to approach that in a modular and reusable way. Since there are already a bunch of very high quality FP utility libraries out there like lodash and ramda, I'd rather not attempt to compete directly with these.

In my mind, a much better outcome would be if those libraries had support for generic collections so they could be used with Immutable.js. Then Immutable.js could reduce its API over time while advertising support for lodash and ramda for more complex and specific operations. I would be very happy to have Immutable.js collections get rid of a majority of its prototype methods if other libraries fill that void.

I'm curious to learn what's missing that would allow this to occur? Are lodash and ramda extremely Array-specific? What would making them more generic look like? Perhaps there's a collaboration that could occur.

@leebyron
Copy link
Collaborator

leebyron commented Oct 3, 2017

A great example of where we've already made progress on this is Transducers support.

https://github.com/cognitect-labs/transducers-js Provides a FP style API that works with Arrays, ES6 Maps, mori, Immutable.js, and anything else that implements the Iterable prototype.

Also, 04e287b added transducer methods to Immutable collections, for even better support (included in the 4.x builds).

This is an example of the kind of thing that does slightly increase build size, but allows for better integration across libraries and could allow us to dramatically reduce API surface area in the future.

@joshburgess
Copy link
Contributor Author

joshburgess commented Oct 4, 2017

I would not be willing to change the immutable-js docs to favor a FP style over the existing OOP style. There's also no demand internally at Facebook for a FP style API over an OOP style API. I think you're right that many developers follow along with what large tech companies are doing, but it would be disingenuous for me to advocate for people to use an FP style API when that's not how we actually use Immutable.js ourselves.

I didn't say that though. I just meant mentioned in the docs as an option, not promoted in the docs as the de facto standard way to use the library. Again, lodash/fp does this. It makes it available as an option for those who want it. Because of the nature of JS, I'm sure lodash/fp users are a small subset of the total amount of people who use lodash, but it's there for those who understand the benefits it allows and want to use it.

In my experience, developers who are new to many of these concepts are far more likely to reject the whole set of ideas if introduced all at once. I don't think the FP style API is objectively better or worse than the OOP style API, but just presents a different set of tradeoffs and each may be more familiar to different developers. Ultimately, the vast majority of JavaScript developers are more familiar with OOP, which is why this library starts there.

It's not really about a style being better or worse, as that's subjective. However, objectively, you can not use currying or partial application with the OOP API as it is right now, and that's frustrating for people trying to advocate for a more functional style in real life each day at their day jobs. I don't think anyone could make a strong case for partial application + function reuse being a bad thing unless they were just simply anti-FP... but you can't do it with immutable.

In practice, this often means either not using immutable at all, dropping out of the functional style when working with the immutable data structures (not ideal), writing your own wrappers each time you use immutable (workable, but hard to get buy in on), or giving up and not using libraries like ramda, sanctuary, lodash/fp, etc. at all, because the benefits just aren't there when you can't consistently use the same style across the whole codebase.

So, it would just be nice to have it as an officially supported OPTIONAL way of working with the library, so that devs could at least point to it and make the case for it when discussing programming approaches with their managers/team leads/etc.

I'm not sure that asking other library authors to support immutable's data types is the right approach. I mean, it's an interesting idea, but there are so many other libraries... sanctuary, folktale, etc.... It would be difficult to make it happen. I wasn't really suggesting that I wanted to use those utility libraries to act on Immutable's collections (although that would be cool), but just that I could use Immutable's own API in a codebase already heavily using currying/partial application without making big compromises or manually writing wrapper functions for each use case.

@leebyron
Copy link
Collaborator

leebyron commented Oct 4, 2017

Sounds like there's pretty clear outcomes here. Let's guide work towards two directions:

  • Prioritize any cross-library protocols that will allow Immutable.js collections to work with FP libraries (like Iterable and Transducer)
  • Advocate for FP libraries - existing or newly created - that can advertise first-class support for Immutable.js collections.

I'm happy to assist with the first of those two - protocols support definitely belongs here. For a new FP library, I'd love to see that occur as a community project.

@leebyron
Copy link
Collaborator

I was pointed towards https://github.com/HubSpot/transmute recently which also may be exactly what you're looking for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants