-
Notifications
You must be signed in to change notification settings - Fork 110
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
Impact of Hack pipes on the JS functional-programming ecosystem #217
Comments
Thanks for trying to emphasize with the people on the F# side even when you are on the hack side. As always which such polarizing issues, people almost never have bad intent, but get very frustrated and upset when they think their arguments are ignored, or misunderstood. But the same people react the same to arguments from the other side due to human nature called confirmation bias. That said, as a disclaimer, even when I try to stay above my own confirmation bias, and try to weigh arguments on their own merits, I'm still biased toward F#. So read with that in mind 😊
I share your hope. But I strongly doubt it. Especially I think that people used to the traditional style and libraries wouldn't even consider using a, in their eyes, new and fancy pipe construct when what they were already doing was already good enough. Otherwise they probably would have done so already using current possibilities like userland
You use this argument more often, but I still think it's a misleading one. Either F# makes an exception for Another thing is: Of all arguments I keep reading in favor of hack, I am missing an in my eyes quite compelling one that I only read in the HISTORY.md file: And although I think they really have a point there, I also think that (although I'm not a compiler expert) this can be optimized later. E.g. when such a function is only used in |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
To be clear, this is still possible with F# style: The difference is that in hack style, this solution is visible by default while in F# style, it requires a lambda. My initial argument was not that it is possible with Hack style, as I believe this problem is impossible to fix in the current language. It was rather that F# style will discourage this behavior by making it more obscure, and that this is caused by inciting currying over multiple argument functions and lambdas. In other words, it's impossible to prevent side effects here because lambdas in javascript cannot be prevented from capturing their scopes, and thus influencing it. On the other hand, F# style appears to me as an opportunity to discourage this behavior. EDIT: I see we're on the same line @mAAdhaTTah :) |
I don't see why, having seen people do this with lambdas in RxJS, your expectation is that they wouldn't do this with lambdas in F#. I don't think the properties of either proposal makes this more or less likely. To expand: at the point which a developer decides they need to make a given variable available outside the context, they're going to drop into the syntax that allows them to do that, for better or worse. In Hack, that's |
This comment has been minimized.
This comment has been minimized.
My opinion on this is based on an idea that I've seen floating around in other thread about the "tax" that comes with each style. People will often take the easier path and by taxing every call equally with some variant of Basically, over time, you would expect to see a lot more code like this: |
@kawazoe |
@stken2050 That is a very hard question to answer. What I bring is my experience working with multiple junior devs on a team and the kind of mistake they often do when dealing with FP style code like RxJs. I cannot tell if Hack or F# style would make it better or worse. I have seen stuff in this proposal that could very well make things worse. Examples like this one: #167 (comment) which to me is a good representation of the kind of code people will write when they don't understand the reason why the pipeline operator exists. Thing is... I don't think it would be any different with either proposals. This is not a Hack style problem, this is an understanding problem. I feel like the F# style, purely based on the assumption that it seems to encourage currying more than the other, is the better choice, but I can't say for sure. Not without trying it in a large scale project with other people. I feel like F# style would be easier to explain to people. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I mean do they override the JS operator functionality of |
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@Jopie64: Thanks! Of course, you are correct here. Everyone, myself included, comes with our own subconscious cognitive biases, and we all have to watch out for them. And it is understandable for people to be frustrated when they feel like they’ve lost something promised.
@Jopie64: Just to clarify…Are you positing that programmers using non-functional programming styles would not find Hack pipes useful for flattening their deeply nested expressions? Hack pipes are designed to be (hopefully) universally useful for all programming styles, including traditional styles—because all programming styles, including traditional styles, involve deeply nested expressions. (Indeed, all of the real-world examples in the explainer are currently based on real-world traditional APIs that are not focused on higher-order functional programming, except for the examples from Ramda’s API (cf. #218).
@Jopie64: This is fair enough, and this argument is well taken. It is true that, although pervasive tacit programming is discouraged by F#’s documentation, The difference is, as you point out, the fact that all functions are automatically curried in F#. And automatic function currying is not built into the JavaScript language, and most functions in JavaScript code are not curried. In JavaScript, curried functions are yet another color of function that have to be used in a special way…presumably with a yellow color 🍛. Although some people like using this color, there are many representatives on TC39 (including outside this pipe champion group) who have pushed back against encouraging currying and partial application. I would amend (and hopefully strengthen) my argument thus: although F#’s documentation does not discourage the pervasive use of its (Though note again that I am in favor of a partial-function-application syntax and an F#-style pipe in addition to Hack pipes. And I plan to try to fight for a PFA syntax and F# pipes after Hack pipes. But it has always been an uphill battle against many other representatives’ reasonable challenges. I have hope that someday we will get PFA syntax, but the hope is small.)
@Joepie: There are several strong concerns that TC39 representatives outside of the champion group have brought. Performance is indeed one of them, although it is not the only one. The browser implementers have said repeatedly to the group that people generally overestimate how much optimization they can do, and they feel that it probably applies to this case (e.g., if a curried function is declared separately—also observable error stack traces getting in the way of inlining). But I think this performance discussion is kind of off topic for this issue. It probably should move to #221. Edit: Oh, wait, you already brought it up in #215 (comment). That’s fine; it’s sort of related. 😄 Anyways, thank you for your erudite and intelligent comment. It also will definitely be important for improving the explainer, too. |
This comment has been minimized.
This comment has been minimized.
@jridgewell @ljharb Similar reasoning blocked ES2015 tail call optimizations from being implemented as the spec mandated by the browsers vendors that use those engines, right? If so, that's a disappointing shared thought impeding a more equitably accommodating pipeline operator for developers to use moving forward. Regardless, functional programming paradigm trade-offs are usually performance-related. That's always a trade-off deciding to solve a problem primarily with functional paradigm constructs rather than using the constructs of other paradigms. Similarly, there are many trade-offs with other paradigms supported by the language being applied to the same problems–it's just that the pros of increasingly applying functional concepts to a problem instead of concepts from other paradigms aren't going to be consistently associated with performance-related benefits. Such paradigm trade-offs should be up to developers to decide what's best for the problem at hand, not the committee or engine implementer teams such as V8's. The language has many constructs for solving the same problems with a variety of paradigms accounted for with varying amounts of performance trade-offs; the robust dev tools we have for developers to use today enable them to make the right choices for their particular situations more than ever before. For example, procedurally iterating things can be meaningfully faster than tackling the same problem more functionally (compared to'Array.map()`; elevated a bit by the use of tranducers, endofunctors, etc). Nonetheless, it's practical and overwhelmingly beneficial to the language you can handle the same problem more functionally instead. A meaningful amount of people prefer doing this to solve iteration problems that aren't performance-critical. Prevalent and well-regarded functional-programming-oriented libraries, compile-to-JS languages, and the developers using such things are fully aware of the performance trade-offs of using the functional paradigm to solve problems. These trade-offs are invaluably worth it for many developers–even if their constructs were all natively possible. Why can't such trade-offs be allowed to accommodate multiple paradigms at the compiler level? It's a state of political-purgatory for tacit-related functional programming constructs. I'm of the strong opinion a more ideology-equitable committee governing a multi-paradigm programming language and representatives of browser compiler team implementing the specs would more transformatively improve the constructs of the multiple paradigms it supports (& even new ones!) without resorting to shutting them down for intrinsically known faults of the paradigm compared to others in performance by having performance standards more equitable of supporting multiple paradigms. This proposal, ES2015 tail-call optimization, Web Assembly Tail-call optimizations, and other proposals intended to transformatively improve the language have been plagued by that not being the case with TC39, as well as representatives of compiler teams after the fact pushing back against ratified functional paradigm constructs strongly desired by those who prefer or want to solve their problems functionally and recursively in the language (what happened to ES2015 tail call optimization in the minds of many). What is going on with the standard process today with many functional programming proposals in recent years has been argued as being effectively thinly-veiled paradigm-construct-segregation. I don't necessarily agree with such perspectives, but I'm increasingly emphatic of those that adamantly believe this with recent developments of this proposal not helping matters. This is disproportional to how transformative improvements to other paradigms–such as class-oriented programming–have been handled to accommodate programmers more invested in those paradigms than others with minimal or no benefit of programmers more invested in other paradigms. An example is ES2015 classes. This imbalance accordingly negatively impacts the ability of the functional programming paradigm to be in more use in JS to the annoyance of millions of developers towards proposals like this being consistently stalled. It is common knowledge that pipeline-operator is one of the most common features developers want in the language; do the champions think most of such people aren't functionally programming in a matter they claim is in the minority? If the current champions do, I beg to differ. Arguably the most celebrated ES2015 features have been ones to transformatively improve the ability to program using the language functionally (i.e., arrow functions). The latent reason why functional-paradigm-oriented proposals are in demand is because the paradigm isn't good enough as it stands today to use it more effectively and more commonly. A meaningful amount of developers want to program more functionally and tacitly, but features such as this implemented as they expect aren't in the language. Accordingly, this is why I'm consistently pointing out @tabatkin's stance on specific styles of functional programming being "maybe always in the minority" is missing a couple of important nuances on why that's a problematic premise on making the operator more tacit. This is also why I think hack-style version of a pipline operator is detrimental to the JS functional-programming ecosystem. The elephant in the room is it's overwhelmingly clear devs who willingly or have no choice of using functional constructs today as they are today in the language do not prefer hack-style. Prominent maintainers of functional-programming libraries tacitly composing functions today like @benlesh have been clear they would rather there be no pipeline operator at all if hack-style's current semantics is the only option. It doesn't add up to me a functional-programming construct is designed in a way to improve JS's multi-paradigm support has such severe issues with devs who program with functional programming paradigm constructs the most (such people will be the primary people that would use this feature regardless of what is ratified) and the very mature and popular functional programming ecosystem in the language. I cannot emphasize enough pipelining is ubiquitously an intermediate/advanced functional composition construct for those very committed to writing things using functional programming patterns. This is again similar to ES2015 classes being primarily for developers very committed to coding scripts in a class-oriented manner. Accordingly, this is why I'm adamant that hack-style impact on JS functional-programming ecosystem is severely negative. It very detrimental impact to the JavaScript functional programming ecosystem has been minimized by figuratively handwaving members of that ecosystem being a minority underscoring the fact that
Native Browser API compatibility (IIRC by @tabatkins?) has also been a common rebuttal that also is ignoring a crucial nuance: Many browser APIs/functions have outputs that are not intended to be composable/chained–nor are they used as part of an output towards a single result you expect from established and ubiquitous pipeline patterns. The use case of most browser APIs is for imperative writing of code that a Web creative or team of them can apply various patterns like the Fascade pattern to more adapt them to their programming paradigm of choice. In addition to the issues for existing power users and devs that depend on a11y/ergonomic technology I outlined here, I again cannot emphasize enough that the hack-style form of representing pipelining is very detrimental to the language if it shipped the way it is designed today. I'm of the firm opinion it's premature for the pipeline-operator standard to go forward without From there, I think partial application spec should be ratified first. After those three things, I can then maybe see it making sense to revisit this proposal.
@jlharb @js-choi That doesn't seem to be accurate; a pipeline operator just indefinitely won't happen with the current make-up of the TC39 committee (and representatives of browser vendors who can unfailingly impact the fate of a ratified proposal like what happened with the tail-call optimization spec). As far as I know, there isn't anything in the standards process that prohibits a standard from being revisited after being denied initially–sorta how the US Supreme Court operates, for the lack of a better example. It isn't unprecedented that proposals are revisited and made into the language after later attempts. ES4 features like classes are now part of the language after their initial iterations failed to be part of the language (some like class fields are well on track of having the same outcome). I think the process of implementing a pipeline operator in JS can benefit of having a similar story with the current proposal being tabled and the idea being revisited in the future. If Hack-style is rejected, alternate pipeline operator proposals would be political purgatory until it can be revisited; in this case, I'm of the opinion the pipeline operator with hack-style semantics without improvement is harmful to the language more than the language not having any pipeline operator, as I've outlined here. If it takes years; at this point I've accepted that. I plan to be survived by kids. If they decide to be JavaScript developers, hopefully they can enjoy a pipeline operator better designed and more accommodating of the ecosystem than the hack-style pipeline operator is today. The latter is what JS overall great despite its many warts and flaws as a language; hack-style again doesn't do them any favors. If my kids happen to prefer or better understanding solving problems functionally and recursively like me, I hope they really enjoy that in my place–even if I die before that happens without using Babel and Safari/iOS Web View apps like I have to do in the present because of the politics surrounding tacit functional programming standards today (V8's infamous decision to block implementing tail call optimizations as originally specced by ES2015 blocks recursive code being written in Node). Proposals that dramatically improve the tacitness of programming functionally in JS are increasingly predictable not being ratified with the current make-up of the committee and the defiance of specific compiler teams implementing them after the fact as well. I'm aware Hack-style proposed by the current champions of the proposal is understandably a simultaneously fair pursuit of attempting to being accommodating of other paradigms navigating the obvious red tape of transcending the tacitness of expressing functional code the committee is very adament of pushing back against. However, it shouldn't be at the expense of its primary audience–functional programmers–and their ecosystems that made the proposal relevant as it is in the first place. Proposals in such a state with such constituents, I'm content with not being in the language–as frustrating it will be for my young self that the pipeline operator variants most want is in political purgatory with other tacit-related constructs. It's no longer a surprise to me anymore.
@aadamsx To be transparent, I was actually reached out to by a previous champion of this proposal during the pandemic, but it was at a time when I was dealing with a family tragedy. I did not discuss it further with them needing to understandably look out for my mental health and support my family during these wild and unpredictable times. Today, I'm still sorting out how committed I can be to a variety of things with things finally becoming normal for me again that I imagine most are going through this year. That said, it seems the pipeline operator has reached a point that the changes I would want to sell would be n/a for the stage this particular version of the proposal or a severely uphill battle because of the reasons I pointed out above. I ultimately prefer prioritizing being increasingly involved with other Web standard bodies that are much more ideological-equitable, diverse (higher priority should be for more women to be involved regardless of their views, IMO), and more democratic (i.e. more emphatic of the desires of the language's ecosystem) in how they're governed than I think TC39 now is for me to be comfortable doing so. This has become apparent to me with how TC39 is handling the pipeline operator standard and how compiler teams have outright deviated and stalled their ratified specs being implemented to the determinant of millions of developers like what happened with ES2015 tail-call optimizations |
My apologies to all participants, but this conversation is getting a little heated and difficult to follow. This repository is not the right venue to air general grievances about TC39’s general process—even if this proposal is a manifestation of that process. (And, as mentioned before, we already have threads about formal usability studies and popularity surveys: #216 and #222. We also have #221 about engine implementors’ concerns about F# pipes, and concerns about the power that engine implementors have on the process probably better belong in #221.) Additionally, in response to this statement:
Although—as mentioned before—this is very off-topic, I’d like to point out that Committee’s members are aware that it could improve in its inclusivity of women and other peoples, and its Inclusion Group is actively working on improving it. @lozandier: For your broader concerns, we invite you to reach out to the TC39 Inclusion Group on Matrix at There is also a Code of Conduct that focuses on inclusivity. Anyone can confidentially contact the CoC Committee if they think that there has been a specific violation. This repository is simply not the right place to air general grievances about TC39’s general process—even if this proposal is a manifestation of that process. For specific questions about usability studies, popularity surveys, or engine-implementor concerns, feel free to leave comments on #216, #222, and #221 respectively. Thanks! 😃 |
I disagree, this is exactly what the committee is for. Developers can already do higher order functional programming via userland implementations. We're the ones that have to decide what to put in the the language with limited syntax budgets. When looking at F# vs Hack, Hack has a clear performance advantage, supports more use cases, and doesn't prevent functional style (it's just a bit more verbose). Why would we choose a dud?
[My own emphasis] I think we're designing the language for 2 very different sets of developers. I do not expect beginners to understand this tradeoff at all. Expectations built up from compiled functional languages will not carry over to ours.
We're attempting to add a pipeline operator, it just doesn't work in the way you're arguing for. I think the developers who want pipeline will be well served with Hack semantics.
People who have strongly held opinions tend to yell them loudly. That does not mean a majority of users would rather we never add a useful new feature. Deadlock like this is not constructive, we would be stuck with ES3 with this kind of behavior.
I struggle to understand why assistive users will have an issue with Hack. Pre-created flow will look just like regular function calls, and basic operations will not require a function wrapper at all. For every usecase that isn't data-last curried functions, the code is measurably improved. |
@jridgewell I have beginners in mind; I've had beginners in mind with my responses from the very start, including one that's one of the most well-regarded comments in this proposal rep. I've shared many responses and perspectives from beginners throughout my responses in this repo over the years towards why I'm adamant that hack-style needs improvements. As someone who interacts with beginners or contributed to works directly for beginners in platforms/entities such as Code School, Treehouse, Khan Academy, Web.dev, General Assembly, and so on, I respectfully strongly disagree with you. I've yet seen a beginner I've interacted with see hack-style being more intuitive or "better". Unsurprisingly, beginners I've exposed the syntax to get hung up on how redundant and more tedious it is to refactor their existing chaining and composition code to use it instead because of the required To beginners I've interacted with, it is more than sufficient that As far as a beginner concept: I cannot emphasize enough that Pipeline is ubiquitously understood conceptually in data science and computer science subject matters as a series of tasks that are passed in the result of the previous task that preceded it or an initial value. The simplest way most languages represent a series of logic blocks/tasks/subroutines that can simultaneously take in a result of a previous series of logic blocks/tasks/subroutines as starting input is a unary function. Accordingly, I'm not sure why TC39 members and this proposal champions suggest that F# forces "expectations built up from compiled languages" for merely ensuring unary functions are tacit, the most common, simplest, and quickest means to compose/chain. It's a chicken and egg problem why it's not more commonly done: Increased prevalence of such programming in mainstream JS is bottlenecked by the lack of a tacit functional composition operator.
It seems you didn't read the contents of the link I provided, nor probably the main argument about this I wrote that makes my stance very clear. If you did, what exactly are you confused about? In general, it seems very clear to me that the champions of this proposal and the committee are at an impasse with the JS ecosystem regarding how faithful to tacitness, a core characteristic of functional programming, new JavaScript functional programming constructs should be. This problem is reaching a climax with how this proposal has developed with this highly regarded functional programming construct by those who want to functionally program more, faster, and better. I'm of the firm opinion that hack-style representation of pipelining is not tacit enough for the following audiences:
This is regardless of what languages such groups were previously exposed to. I don't think the champions nor the committee are thinking enough of the middle audience. "Beginners" are very hypothetical of an audience compared to all three that ironically would need the most quantitative data to support all audiences. The champions of this proposal have made it clear they don't want to do that being very unprecedented to do. I would like such an audience to be referenced less in such discussions accordingly. I believe that a proposal shouldn't weigh too much on the opinions of the masses, but there is a diminishing return of going that direction that this proposal has reached with hack-style in my opinion. I'm merely doing what I think is the right thing to let the champions and committee know this very explicitly. That said, I wonder: Has a variant that only works on arrow functions been proposed? As a creative suggestion, perhaps that can be a path towards a compromise? I'm not convinced hack-style is the right one. Alternatively, what do you think of the compromise I explained last year](#225 (comment))? I think it should seriously be considered; it's very simple to understand non-functions would use In comparison, Hack-style's unorthodox handling of pipelining is contrary to how pipelining is understood conceptually by most, creating a lot of unnecessary cognitive noise–that's incompatible with the majority of the JS functional-programming ecosystem today. I'm of the opinion it's too much of a hack. |
The argument I made was that beginners will not understand the performance penalty they are paying, not that people who are being explicitly taught tacit functional programming will find the tacit syntax more pleasant (of course will). But they will not understand the reason the JIT can't inline the closures, or why their computation is thousands of times slower.
Again, this was explicitly about the performance penalty because a compiled language can eliminate the closure allocations, where JS will not.
The same thing Tab is confused about. Tacitness at a single expression does not change the entire language and ecosystems that have been built on the way the language is now. And frankly, it's only terser if your entire program was built with a functional style (no codebase I've ever worked in was built that way). How am I to use all of the non-data-last-functional functions I've written in a F# pipeline? Wrap them in arrow IIFEs? How is that not an accessibility concern? My point, and Tab's, is that Hack integrates better with the entire language, where F# integrates only with functional programming.
How are these not solved by https://github.com/js-choi/proposal-function-pipe-flow? You can even hoist this out of your hot-path and reap the performance benefits, something that's not possible with F#.
I've been vocally arguing for https://github.com/tc39/proposal-call-this/ because I value the tacit style it allows. I'm, however, not willing to accept a pipeline operator (F#) which we already know before standardizing must never be used in performance critical code, when we can choose one that can work perfectly (Hack). Call-this allows functional left-to-right tacit data flow, and it doesn't suffer from the death-by-closures performance penalty. But I don't imagine functional programmers will be happy with that one either. |
@jridgewell Thousands of times slower compared to what? Doing explicit manual composition/chaining
I explicitly made this clear with the response I pointed to you several times now that Tab doesn't seem to be confused by; I'm genuinely confused about what you're confused about regarding the following excerpt:
With all this said, I believe I sufficiently addressed With the pipeline proposal, many wanted the tacitness that If hack-style is the last-ditch effort to provide a pipeline operator for now; I think it should be on hiatus for now, similar to what happened to container queries in CSS until compilers and champion/committee opinions changed from later enhancements of the language illuminating what to do it to be adequately implemented. It's arbitrary to release pipeline operators this unorthodox to the JS ecosystem and the expectations of many who wanted it in the language. It seems premature to be ratified without partial application standard and
Partial application for starters (a factor of why I think this proposal is premature without it existing in the language first and
I'd refrain from speaking in absolutes about that being demonstrably false by the many examples I and others have shared for years in many issues in this repo who may likely coincidently code functionally more frequently than you. I'd revisit why you think this way to avoid such an extremely false standpoint be iterated again. |
Than Hack style, which can be seen as nested function chaining.
The penalty of using a
Three is no binary operator that behaves like either F# or Hack pipeline, so there is no precedent in binary operators to break with. There is precedent from your particular flavor of functional language for F# pipeline, and there's precedent from Hack language Hack pipeline. There is no precedent in JS.
Hack is less verbose than the nested function calls it'll replace. It's more verbose than F#, but that is not an issue.
Both Tab and I do not understand this point. How does Hack harm assistive users?
As a user of Vim for a decade, I have no idea what is meant by this. How am I negatively impacted by Hack?
It's more verbose for functional programming users only. It's less verbose for every other type of expression. Given I've never seen a large scale functional codebase in JS in all my years, I'd prioritize making functional programming less verbose as a non-goal.
Hack literally helps with every function call, except for data-last curried functions. The overwhelming majority of code, I'd say. You're literally arguing for a worse experience for the majority of the language because you can't see past your niche. Closure-returning unary functions is not so prevalent that we should be ignoring every concern the committee has raised.
Easier to write? And how about read? Having to maintain a nested parens counter in my head while I parse someone else's is a major pain point in language. Hack's
Again, it helps with everything except the niche data-last curried function. It's orthodox with the rest of the ecosystem.
As mentioned in my previous comments, the committee is reluctant to add syntax that will have large performance penalties. Partial application is going to have its own uphill battle without even adding the baggage of F# pipeline.
Comparing
Demonstrably false? Please link to large scale JS codebases that are using functional programming extensively. I would be flabbergasted to find that functional style is anything more than a niche. |
Majority of people using the language today (including beginners from my experience) want merely a tacit functional composition operator; like I said–since hack-style intends to be utterly unorthodox to this–I think it should not be the only pipeline operator in the language, nor be at the expense of such a pipeline operator to substantially make more useful existing functional programming constructs like arrow functions and make a variety of functional programming patterns more prevalent discussed very thoroughly in #238 and #237. Suppose this is too contentious or impossible to accommodate with the current champions and committee. In that case, serious consideration should be made to have pipeline operator on hiatus till improvements to JS compilers + ecosystem sentiments of related and more focused proposals can be evaluated, such as Container queries in CSS benefited from this approach; pipelining being similarly transformative that dealing with uphill battles of getting consensus on how it should work technically and semantically. Similarly, in JavaScript history, ES4 constructs like classes and class fields benefited from being postponed.
This is demonstrably false again, which is something raised extensively in #238 and #235. Another excerpt from the former helpfully presents why this is.
f(g(x))
x |> g |> f
x |> g(^) |> f(^)
For this reason and other reasons I've extensively raised, I think the bubble of hack-style's verbosity not being an issue should be debunked.
Uh… False. I've demonstrably explained this very thoroughly in the links I've already provided you:
From my experience beginners, data science/ML colleagues, and various other programmers who are familiar with tacit functional composition encouraged by popular functional programming, and myself don't have such an experience. As I stated many times in our debate,
It isn't and #238 and the original comment I provided thoroughly debunks this. What's more terse/tacit than Function.flow is the far more tacit representation of functions via F# pipelining such as I encourage you to find time to enlighten yourself about that.
Again the following succinctly answers that for you, in my opinion:
This is further exacerbated by those that leverage braille; this is not unlike the problems of using two spaces versus tabs for those that are non-maliciously ignorant of such caveats. For these reasons, and those that compose a lot like me for data science/ML use cases, tacitness is very much beneficial with introducing new operators as a core characteristic that hack-style pipelining outright omits, unlike other binary operators in the language. I cannot emphasize enough that JS's existing binary operators are less verbose alternatives to the expressions they abbreviate; hack-style again violates this latently communicating functions should be an exception to such tacitness ("point-free") that a meaningful amount of the JavaScript community disagrees with.
As a decade Vimist myself, there are several issues with hack-style that I again pointed out extensively in #238 about how it impacts power users such as ourselves, in addition to what I just said in the previous rebuttal:
From my employer alone, most modern Angular projects used by millions of users leverage reactive functional programming constructs heavily via RxJS; it is very much desired for a more tacit representation of such code via a native functional composition operator the pipeline operator was supposed to be. That said, I have a suspicion you have a narrow perspective on what functional programming is. In the real world, code rarely is without patterns of multiple paradigms at play. For this reason, I'm confused why people are adamant about describing or identifying themselves as a developer using a specific programming paradigm. I guess the everyday person is used to such tribalism behavior with how people associate themselves with political parties and sports teams. All that said; similar to quotes vs. backticks and how seamless to switch between the two, I'm adamant a florian's compromise is code such as the following: // Example in Readme from react/scripts/jest/jest-cli.js with the two pipeline operators utilized
envars
|> Object.keys
|>> ^.map(envar => `${envar}=${envars[envar]}`)
|>> ^.join(' ')
|>> `$ ${^}`
|>> chalk.dim(^, 'node', args.join(' '))
|> console.log;
// |> is explicit pipelining (tacit functional composition/F#-style)
// |>> is implicit pipelining (topic-style/Hack-style)
// Note that ligatures conventionally exist for |> and |>> in typefaces designed
// for programmers. In performance-critical apps/scripts, |> can be banned
// by linters similar to native array methods for iteration use cases because the
// intermediate arrays they create without userland variants w/ tranducers. Unfortunately, it seems you and other committee members are adamantly against more tacit functional constructs being in the language despite the rapidly increased prevalency of functional programming today that is in need of more tacit means of composing functions that led to the demand of the operator in the first place; I'm very unconvinced about your readability concerns that is not cosigned by a majority whatsoever in #225. You claim such readability familiarity is a niche, but it can be argued you aren't "reading the room" not considering that your limited capability to find tacit functional programming readable is contradictory to the familiarity of such things by modern JavaScript developers today. Accordingly what is going on can be seen as gatekeeping from a superminority position. To your credit, you at least own this:
Even the most popular JS framework today (React) is functional to the extent such tacitness is not abnormal, as well as others like Angular (reactive functional programming constructs) that are less functional but very much exposes their developers to tacit functional programming via A meaningful amount of people want to tacitly compose with functions with the same level of tacitness primitive values have with binary operators such as As for myself, please refrain reducing me being an advocate for functional programmers in further discussions about this; I've made this very clear in the response I originally provided you to review:
General problem solvers include beginners and various members of academia that very much would like to see a more tacit means of composing functions in the language as well. Hack-style does not accommodate them either regarding that. |
Based on what? This is not the way the committee is interpreting this. We're proposing an operator that accomplishes left-to-right flow, which we think is the core desire.
Again, the committee is rejecting this as a non-goal. I reject this, if for no other reason than the massive performance penalty this will incur.
Throwing the entire proposal out because you don't get everything your way isn't a productive way to run a committee.
The committee has expressly designed for "one JS", meaning we do not want to promote compilers and other build systems as the only way to write effective JS. Having a feature which can only be implemented effectively via a build step is not going to be popular.
Cool. For any on contrived example (multiple or complicated arguments), code is split into multiple statements: const gOfX = g(x)
const fOfGOfX = f(gOfX) So,
Remind me again which binary operator invokes its RHS with the value of its LHS? I think our mental models for how binary operators work is very different. There is no precedent to break.
How is the
The code example was comparing console.log(
chalk.dim(
`$ ${Object.keys(envars)
.map(envar => `${envar}=${envars[envar]}`)
.join(' ')}`,
'node',
args.join(' ')
)
);
// vs
Object.keys(envars)
.map(envar => `${envar}=${envars[envar]}`)
.join(' ')
|> `$ ${^}`
|> chalk.dim(^, 'node', args.join(' '))
|> console.log(^); I think it's clear which one is easier to parse.
Please provide an example of these binary operators.
The choice between Hack and F# does not change the rest of the entire language. This is not going to hurt braille users any more than calling
None of these are real issues:
The difference between
Are you forgetting about the
Good, we want to actively discourage that kind of performance penalty.
I, specifically, am against the performance penalty that this style of programming will encourage.
Personally, I find the functional programming that redux encourages to be the least understandable part of modern react. Core react has no such crap.
You're gonna have to explain this one. |
Have you ever used Angular? Because this kind of answer makes it looks like you didn't even took the time to look at their sample application... completely disconnected from the reality of people writing actual application code... Everything in Angular uses Rx Observables instead of Promises. It is designed for you to to use You want to monitor the changes of a value in your template? That's a pipe. Everything in an Angular app gets wrapped up in functional style code, creating more closures every single time. If you're not doing this, you end up with race conditions everywhere in your application. It is meant to be used this way. I am with @lozandier on this one. My last project was a mobile application built with Ionic 5 + Angular + NgRx. Most modules of our app made heavy use of RxJs because Angular is designed for your to do so and those pipelines could go for hundreds of lines. We had over 250klocs in the project, nothing was lazy loaded, and it worked without a hitch on a 5 years old Android phone. I am sorry to say this but... with an answer like this, you have lost all credibility to me... |
My only thought was of the places that use the tacit style as in https://angular.io/guide/pipes. The dialect is only in the templates, and I should have considered that RxJS is used throughout Angular apps because it's encouraged by the core lib. |
Gentle reminder that all participants are expected to abide by the TC39 Code of Conduct. In summary:
|
@jridgewell You missed essential feedback on why the proposal is being desired then. I again explicitly addressed this in #238. As I stated throughout that issue: Left-to-right functional composition flow is quintessential to any pipeline operator, and very much right after it–facilitated by the fact that functions are first-class values in JavaScript–enabling tacitness that’s impossible by userland abstractions is very much expected and desired to align with the existing binary operators in how tacit it is.
For beginners and experienced developers alike (anyone who passed high school algebra, really)–as well as potential/casual JS users well versed in composition via disciplines such as general Math, Statistics, and so on I work frequently with–it’s confusing to them why they can’t abbreviate composing functions as tacit as you can existing binary operators such as The tacit equivalent in math for functions is the functional composition operator (∘); it allows the same level of brevity to represent composition with functions, as demonstrated straightforwardly on wikipedia:
Accordingly, it can be argued that hack-style breaks the principles of least surprise. You have to use |> and I find it trivial to explain to multidisciplinary beginners and developers that Again, this includes people who are casual users of JS and will use it on things like Google Sheets’ AppScripts. I immediately picked up such issues when such people were exposed to hack-style in contexts as casual as those. Accordingly, I’m adamant you and other committee members have very noticeable gaps in your understanding of what developers and general people primarily want/expect from the operator. A significant number of developers want a more fluent, tacit language to use; hack-style is a considerable step back from this expectation, making more verbose widespread expressions in JS and math: Chaining and composition. Working on data processing/ML pipelines and cloud functions frequently for my job, I’ve greatly benefited from modeling things in a pipeline matter left to right. It’s ubiquitous doing so to solve the problems I solve. The pain points colleagues and I have more have to do with the lack of a more tacit means of expressing such things that coincidently mirrors the pain points that @benlesh pointed out in #238, who already maintains the non-native equivalent to Hack-style merely as a way to show processing left to right that is more verbose than composing and chaining with what exists today natively in the language–and what’s available by the existing JavaScript ecosystem–is very much useless to such a demographic as it is for the functional programming ecosystem.
… Isn’t that the reason we have proposal stages for this to happen potentially beneficially for the language progressing with well-scrutinized features? Some proposals are too contentious to be done, which is meant to be discovered during the process as a recognized outcome of the proposal. This proposal is reaching that point with a pipeline operator fundamentally incompatible and at odds with the current JavaScript ecosystem. According, it again makes sense to postpone this proposal until the partial application proposal and Hack-style prematurely adds a placeholder token that should probably be sorted out by the partial application proposal first. The fact that it may now become two characters to signify just a placeholder ( Any way you look at it, I’m increasingly convinced it’s harmful to the language to be forced on expressions merely communicating unary functional composition, which is very common for people across many disciplines and industries that want to use or have to use JavaScript for some of their problems that need to be done using a JavaScript runtime.
I did not suggest a build step whatsoever. You’re arguing a point I did not make; it seems you’ve misconstrued me with my use of “JS compilers.” I’m talking about native JavaScript engines such as V8, Spidermonkey, and JavaScriptCore. I apologize for confusing you here.
…Stunting the growth of the functional programming paradigm on the platform as though it will cease to exist if you neglect it enough is not helpful. I firmly believe that an essential aspect of managing a multi-paradigm language is equitably improving the supported paradigms. There are tons of beneficial things in JS and its ecosystem that are functional or depend on things heavily invested in being coded in such a way. This stance substantively limits these things from getting immeasurably substantially better, dragging the entire Web and device ecosystems down in how good they can be since JS is the only core programming language you can currently use on the Web and the most reliable programming language devs can rely on being available on most devices. Class-oriented programming paradigm needed transformative features like classes, class fields, and private methods to be significantly more helpful for those invested in coding that way and those who have to deal with that style of code against their wishes. Functional programming needs to be equitably similarly improved for it to be easier to use for people who are committed or stuck with using its constructs in scripts which isn’t uncommon at all whatsoever. Despite its inherent flaws in performance, functional programming is here to stay. There’s more to good code than pure performance metrics; performance isn’t everything. Functional programming is more prevalent than ever, despite how disproportionately it’s accommodated by committee members such as yourself. Regardless, the solution I provided you in my previous response is an explicit example of substantially minimizing your performance concerns while eliminating both sides’ contentiousness. The con is merely the burden on implementers that have already overstepped/exploited their influence like what the V8 team did to ES2015 tail calls in the minds of many. Like the Go compiler implementers giving in to the needs of a meaningful amount of developers to support generics despite its inherent performance issues as a construct and the burden on implementers, the pros of having a tacit functional composition variant of the pipeline being available to the JS ecosystem outweigh the cons–the same thing applies not having a pipeline operator if it means we’re stuck with hack-style indefinitely to respect the current stage of the pipeline operator. This generation of committee members doesn’t seem ready to do so with the pipeline operator; accordingly, I’m increasingly convinced it’s not a good idea for the pipeline to continue as is when it’s premature to do so when There’s no mistake people want more fluent code being possible in JS; Hack-style is a step back regarding that for everyone being more verbose than what it’s replacing—which may be worse based on recent developments that may suggest the placement placeholder may require two characters such as The community behind a language is vital, and hack-style currently lets many meaningful people down with such semantics in its pursuit to avoid functions being composed as tacit as other binary operators that already exist in the language. When I read stances like yours, I begin to wonder if people overseeing the pipeline proposal think hack-style will release as is towards suddenly an alternate universe existing in which it’s not incompatible with a meaningful amount of the JS ecosystem and how millions of developers functionally compose in a pipeline manner today. Those are both red flags that it probably shouldn’t proceed without tweaks.
I’m not sure where you’re getting f(x) from; it’s For contrived closure functions like the following code snippet 2 |> add(2) |> console.log being compared to the code snippet below: 2 |> add(2)($_) |> console.log($_) // $_ replacing ^ now Regardless the hack-style representation of pipelining is undesirable, being far more tedious to read, type, announce and understand than just the following code snippet. console.log(add(2)(2)); This is again unprecedented for a binary operator in the language. Accordingly, I’m of the firm opinion that Hack-style’s semantics for unary functional composition expressions is not helpful for a meaningful amount of users accounting that won’t go more advanced than that with their practical composition needs. const gOfX = g(x)
const fOfGOfX = f(gOfX)
I don’t think that example is that convincing whatsoever. You showed off hack-style is more tacit than very contrived imperative code (why not explicitly compose the two functions; what do you need two variables for this?) yet more verbose than native represention of that composition ( Most functional code today is more tacit than that example and hack-style, which is now more likely,based on recent developments in #91, the following: input |> func1($_) |> func2($_) I’m not convinced this is a direction the language should go whatsoever. The typing complexity associated with that coding example makes my ring and pinky fingers hurt just glancing at this. I can’t help but think the following thought that’s similarly echoed by beginners–as well as industry colleagues I’ve shared hack-style syntax with–when I see code like this: Is JavaScript trying to be as verbose as Java in an attempt to block point-free programming? It’s a regrettable situation. I never thought hate for a particular programming style could be so deep to believe such a verbose alternate is OK. I want JavaScript only to be similar to Java with its first four letters, please–for the sake of the ecosystem. Hack-style as-is is contradictory to this. Edit: After it was clarified a more independent route of addressing my concerns can be feasible in the future, contrary to what I interpreted from strong stances expressed to me recently, I will bow out of these discussions indefinitely accordingly. My feedback regarding hack-style pipes impact on the functional-programming ecosystem can always be revisited whenever it next makes sense. |
Thanks @lozandier for relentlessly defending against the Hack proposal. I don’t even consider myself a functional JS developer. I don’t care much about partial application, and I don’t go out of my way to use immutable data structures (though I am looking forward to JS having proper immutable data structures in the future… until then TypeScript’s But I am doing a lot of @jridgewell wrote:
That may be your opinion, but in my experience, that doesn’t jive with how most JavaScript developers see or use the language. In fact, your use of language here to me suggests you may be severely out-of-touch with the landscape. As for the Hack-style proposal, I’ve made my protest known before: I agree with @lozandier that I see more harmful effects to the language than I see benefits. I’d rather have no pipe operator at all than Hack. |
I will once again remind everyone that TC39 has a Code of Conduct, and comments such as the one I've just deleted are obvious violations of such and will not be tolerated. |
It jives with my experience, and I'd suggest the development of RTK to simplify a lot of the boilerplate involved in Redux is evidence to support that assertion. RTK is also taking a lot of inspiration from react-query/SWR to simplify that boilerplate, and only uses thunks, rather than any of the more complex/functional approaches to side effects. I think it's also notable that React core did not integrate any of the purely-functional approaches currently in the JavaScript ecosystem when adopting Hooks. While they're inspired by Algebraic Effects, Hooks are only inspired by them, rather than integrating them whole cloth, and the pain of dealing with higher-order components, render props, etc. is a big part of what pushed them in that direction. |
@mAAdhaTTah I think we’re talking past one another here. As I mentioned I’m not a functional JS developer, so arguments about purity don’t resonate with me. But as I said, I do use a lot of The thing is though, as I also mentioned when I talked about readability concerns, I don’t think most imperative code examples get improved by Hack at all. And they wouldn’t be improved by F# either, so quoting Dan in that context doesn’t work for me either. I actually like plain, simple, imperative, I was slightly sympathetic towards Minimal/F# exactly because I felt it was limited to well-scoped use cases, but somewhere it appears some convinced themselves that all code should be written as pipes, which is a position I would not embrace regardless of which proposal. I’m really fine without pipes. And that, I genuinely feel, is the position that almost all React developers I interact with share. |
Dan in that comment elaborates on how everything is function calls, and Hooks in particular are not tacit, by and large, so no, I don't think tacit programming is encouraged by React. |
|
Mostly correct (tacitness isn't related to inner mutation, just point-free style), but hooks are not typically called tacitly. They're called the "standard" way, with parens, and with their arguments/"points" explicit. So no, React itself does not encourage tacit programming. I'm also not splitting hairs. I'm drawing parallels between React's design philosophy & Hack pipeline's design philosophy. Both are attempting to take inspiration from approaches & techniques outside of JavaScript mainstream (or JS entirely) and modify them to fit more cleanly into the language, given its affordances. Looping back to where we started:
If we can accept that the React core team has a much broader view of the ecosystem than we do, then it speaks volumes that they explicitly decided to forgo a more tacit/functional approach when introducing Hooks, which says to me that JavaScript developers do, in fact, "find the functional programming that redux encourages to be the least understandable part of modern react". Redux itself adding hooks while RTK forgoes higher-order components & |
@mAAdhaTTah Yikes. It appears I’ve been using the term tacit entirely incorrect then. Somehow “point-free” had been warped into preferring functions over methods (ie. avoiding the dot — Dutch: punt). Apologies for the confusion. But yeah, what I meant to say was that I primarily use plain functions that are invoked imperatively. Despite being influenced by functional programming (avoiding mutation, the occasional higher-order function), I don’t go all-in on the functional style. That is the style I have mostly adopted thanks to React and Redux. Hooks are fully compatible with that. As is Immer, because despite using mutation-style syntax, it upholds the immutability at a higher level, which is the part I care about (side note: this is also one of the things I love about Rust, because it gives you mutability guarantees, without needing special immutable data structures and allowing mutable operations at the local level… kinda like Immer without the downsides). So that’s what the majority of my (and around me, most people’s) coding: plain functions and immutable data. But that coding style also doesn’t really get improved with a pipe operator. There is the odd exception, of course, but I really wouldn’t want pipes in most of my code. For the exceptions, the F# version would be fine. And because it’s so limited in its scope, that would be the only place where it gets used. The Hack version is so flexible that I frankly would eliminate it entirely through ESLint to avoid the bike shedding over which exception warrants its use and which doesn’t. |
Ah, that explains a lot. I will say, it sounds like we code fairly similarly, but I have found that, even if I'm not doing "deep" FP-style code, if I lean on functions a lot, I still end up writing sequences where the intermediate values don't matter. But we've discussed this in depth elsewhere so I won't continue here. The main thing I wanted to emphasize is that the design of React and the design of the Hack pipe draw from a similar underlying philosophy. |
I really like the terseness of F# pipes and don't want to give it up hard, but I can see how hack pipes bring a lot to the table when using non-functional JS features like class constructors, calling non-curried functions. I don't know whether there were a discussion about that already, but this hack pipe kind of looks like a combination of F# pipe and one specific Scala underscore syntax usage: // in scala you can do
val prices = Seq(10.00, 23.38, 49.82)
val pricesToInts = prices.map(_.toInt)
assertEquals(pricesToInts, Seq(10, 23, 49)) I was wondering maybe this proposal can be split up into two things:
After that we could achieve something similar to hack pipes with [' a ', 'b', ' c ', ' ']
|> %.map(%.trim())
|> %.filter(Boolean) while still supporting terse syntax import { filter, map, trim } from 'whatever-fp-lib.js';
[' a ', 'b', ' c ', ' ']
|> map(trim)
|> filter(Boolean) |
After thinking about it more I can see that this potential
I just find it weird to have a special symbol that only works inside a pipe chain. ' a' |> %.trim() // I can do that, % behaves like (x) => x.trim()
// but
[' a'].map(%.trim()) // I can't do that, % doesn't exist |
Yup, you're essentially reinventing the Partial Function Application proposal ^_^ There are unfortunately still several issues with this: it's extremely difficult to generalize past function-calling without some wild grammar contortions, as you've found; it doesn't work with
If it helps, don't think of it as a "special symbol", but just as a variable name. Variables only have values in contexts that define them; the topic variable is only defined by the pipeline syntax. |
Regarding referencing Dan / React Team and referencing them in context to the impact of the JS functional-programming ecosystem
@mAAdhaTTah It’s not implausible the React Team merely designed the Hooks API around the people that have formed around the people contributing or using their library canonically or they’re inferring in advance. An empathic team of objective and professional engineers typically will not shoehorn a particular paradigm in their API at the expense of their users or the happiness/capabilities of most contributors willing to work on a particular API. It is dangerous and daresay naive to extrapolate such experiences for or for against a language-wide feature such as this–let alone undermine the reactions of the broader JS ecosystem that is far bigger and far more important than React (to no fault of React; React is an invaluable library for very specific front-end problems). React is ultimately a front-end library, its use is very limited in application of a feature that is to be used and can be used to alleviate things such as
Overall, it’s a reach to suggest a library is being averse to a paradigm for decisions that are unlikely paradigm-driven in the first place in the best interest of the community that use or contribute actively to the library. Such decisions are more natural to be based on the skillset of the contributors that were around at the time core architecture decisions were made around the feature that would be too much cognitive noise and work to pivot dramatically from due to the opportunity costs of deriving more meaningful value elsewhere instead among the many things they have to work on maintaining an open source library being continuously worked on, forked, and used by millions of users. It’s inappropriate to infer what you’re inferring ultimately without perception checking with the React team or at least directly referencing their explicit stance on what pipeline operator they prefer. @gaearon (Dan) is a very open-minded, transparent, and empathic open-source contributor; it seemingly would make very much more sense to mention him explicitly and perception check with him your perceptions of the affinity of this potential language feature after all this time rather than run away with your conclusions that impact a standard in a matter that the JS ecosystem and an abundance of experienced, notable JS developers such as @benlesh have made very clear Hack-style is harmful to the language to the extent they would rather have no pipeline operator at all if it was the only pipelining option. Furthermore, Dan's not the whole React team; you can't infer his opinion is shared across the whole team as it seems you are doing to me. Note I'm well aware of Dan's stance; as a matter of fact, my well-regarded proposed solution–the most regarded proposal in this standards repo thus far by likes– actually had his stance in mind. I find my proposal alleviated his concerns by making Hack-style have a "backtick string interpolation" role as a pipelining option compared to F#-style as the primary/default one my solution proposed. I find hack-style a good fit for JS if it was the “backtick quote” role (pipeline templating/literals; readability and writeability of method chaining when your component expressions aren't methods) out of all pipelining options in the language, allowing arbitrary expressions of pipelining that are also easy to lint (require it for all pipelining or outright ban its use for pipelining by entities using JavaScript in a variety of sophisticated ways). This is easily teachable as analogous to the string templating features added to the language using backticks and string template literal functions. I absolutely don’t think Hack-style should be the only or main form of pipelining in the language. From a purely academic/educational and multi-industry standpoint (AI and data science) multiple products at an enterprise level while simultaneously working with developing engineers all the time, I’m of the strong opinion F#-style is far more
// F#-Style
class Comment extends Model |> Editable |> Sharable {}
// Hack-style: I've yet to see a Researcher, Engineer, or Intern/Student not find the Hack-style variant odd and unnecessarily arduous.
class Comment extends Model |> Editable($_) |> Sharable($_) {} Furthermore, and most important to this thread, F#-style is without a doubt far less obtrusive to the JS functional-programming ecosystem by only alleviating the barrier of using or even needing libraries to represent tacit functional composition pipelining that are among the most used libraries in the entire ecosystem. Aligning with their mature and well-thought-out semantics, It deprecates/eliminates the need for many of them overnight in a style understood and fetched millions of times by JS developers over the years. This would save a decent amount of kilobytes in many Node/direct-to-browser JS projects overnight. What makes this dragged out is TC39 members who arbitrarily want to limit one way of pipelining in the multi-paradigm language. Using Suggestions to improve how you reference the React Team and other JS library teams to be more meaningful to the progression of these discussionsA more interesting question to ask, similar to what led to generics finally sensibly getting into Go, is how would the React codebase/API change or be improved if F#-style and/or Hack-style existed in the language when they designed React and its recent features? Kubernetes did this to finally enlighten the Standards Committee around Go to finally give generics in Go more serious consideration. If Standards committee members like you have so much reverence to React to reference them towards your stance on a language feature, perhaps it's worthwhile to consider requesting them to do a case study to help out with this standard? I find that significantly more convincing than how they're being referenced in this standard repo thus far–especially when standard committee members conflate independent libraries with unknown affinities such as Redux in these discussions. @tabatkins understandably made it clear there won't be further JS ecosystem-wide research questionnaire surveys pursued towards this spec being ratified. I find case studies from prominent JS library maintainers a distinct and worthwhile alternative to consider (Libraries keen on pipelining in the first place or find its absence in the language a huge pain being prioritized). |
Spinning this out of #202 (comment).
Lots of people have expressed concerns that Hack pipes would silo the community of JavaScript tacit-programming (aka point-free style). These fears are understandable. And we are sorry for all the frustration that people who like tacit programming have had—feeling like something was promised but taken away. (See #215 and #206 (comment).)
However, we are hopeful that the opposite of siloing will happen: we are hopeful that Hack pipes would actually help increase interoperability between functional APIs and non-functional APIs. We’re hopeful that this increased interoperability would decrease siloing, rather than increasing it.
(By “functional APIs” I do not mean only tacit programming but libraries that identify as “functional APIs”. Also, as a reminder, tacit programming / point-free style is not the same as functional programming. Tacit programming is only a subset of functional programming. In fact, much functional programming is pointful (e.g., with Haskell
do
notation). The debate over tacit programming versus pointful style has been a long and controversial one in the FP community for many decades.)The pipe champion group thinks that keeping userland tacit
rx.pipe
-style functions within internal code is okay. In fact, that’s what F#’s documentation itself suggests:In other words, it is true that Hack pipes would keep tacit programming in userland functions and not in the language’s syntax, and that is disappointing to many people who like tacit programming. But we are hopeful that Hack pipes would increase interoperability and decrease siloing between functional libraries and non-functional libraries (and, as F# suggests, tacit programming should be kept internal anyway). I know that not everyone in the community shares this view, and we won’t be pushing for advancement for a while anyway, but hopefully this logic can assuage some fears.
(To emphasize, it is likely than an attempt to switch from Hack pipes to F# pipes will result in TC39 never agreeing to any pipes at all; syntax for partial function application (PFA) is similarly facing an uphill battle in TC39 (see HISTORY.md). I personally think this is unfortunate, and I am willing to fight again for F# pipes and PFA syntax, later—see #202 (comment). But there are quite a few representatives (including browser-engine implementers; see HISTORY.md about this again) outside of the Pipe Champion Group who are against improving tacit programming (and PFA syntax) in general, regardless of Hack pipes.)
In any case, the explainer does not talk about the impact that Hack pipes may have. This is a deficiency of the explainer. We need to fix this sometime.
This issue tracks the fixing of this deficiency in the explainer (lack of documentation regarding projected impact of Hack pipes on the functional-programming ecosystem and decreasing of siloing). Please try to keep the issue on topic (e.g., comments about the importance of tacit programming would be off topic), and please try to follow the code of conduct (and report violations of others’ conduct that violates it to tc39-conduct-reports@googlegroups.com). Please also try to read CONTRIBUTING.md and How to Give Helpful Feedback. Thank you!
The text was updated successfully, but these errors were encountered: