15 ms·
I'm a fan of functional programming but I'm pretty sure this post would do a terrible job of convincing anyone to try FP out. There's a very bad pattern of repl
by steinuil 4y ago
I'm a fan of functional programming but I'm pretty sure this post would do a terrible job of convincing anyone to try FP out. There's a very bad pattern of replicating very specific language features and control flow structures just to make them more similar to point-free Haskell, which is not going to win anybody over.
The author begins by replacing a language feature, the . operator, with a pipe() function. After that they swap out exceptions for Result, null/undefined for Maybe, Promise with Task, and the final code ends up becoming an obfuscated mess of wrapper functions and custom control flow for what you could write as:
fetch(urlForData)
.then(data => data.json())
.then((notifications) =>
notifications.map((notification) => ({
...notification,
readableDate: new Date(notification.date * 1000).toGMTString(),
message: notification.message.replace(/</g, '<'),
sender: `https://example.com/users/${notification.username}`,
source: `https://example.com/${notification.sourceType}/${notification.sourceId}`,
icon: `https://example.com/assets/icons/${notification.sourceType}-small.svg`,
})
)
.catch((err) => { console.log(err); return fallback });
...which is just as functional because doesn't involve any mutation and it doesn't require several pages of wrapper functions to set up, you can tell what it does at a glance without having to look up any other pieces of code, it's gonna run faster, and it uses standard control flow which you can easily debug it using the tools you use for any other JS code.
This post has nothing to do with functional programming, this is a poor monad tutorial.
- Kerrick 4y agoYour response describes exactly how I felt using RxJS for the first time.
- dmitriid 4y agoIt took the author of RxJava months to understand the concept. Screenshot from the book: https://twitter.com/dmitriid/status/811561007504093184 https://twitter.com/dmitriid/status/811561007504093184 (Jafar is the author of Rx .Net, and even he couldn't explain it to the future author of RxJava :) )
- dtech 4y agoI've been working with Rx for 10 years or so and I think it's a terrible model. If you need processing of streams of asynchronous dynamic ("hot") data it's the least-bad model I know, otherwise there are much better ways, especially now that many languages have async-await keywords or at least a Future/Promise type.
- halpmeh 4y agoAsync await is way worse for serious async processing, mainly because handling cancellation sucks.
- antihero 4y agoI found using rxjs with redux to be a way of decoupling control flow. Instead of having a function with a bunch of thunks, you did something and then other bits of code to could effectively subscribe to the side effects of that and you built your control flow up that way. It had pros and cons, was quite powerful but you ended up with a lot of indirection and not exactly knowing what was going to happen.
- Cthulhu_ 4y agoI've only been using RxJs for a short while now (we're moving to react soon), I don't really get it. I mean I get it, just not why we're using it just to consume some REST APIs. 80-90% of that is boilerplate code to please RxJs, and only alll the way down through two layers of stores / states and a library another team maintains is there a single call to `fetch()` that does the actual work. I'm pushing to use react-query with the new app, I think people will get confused when it turns out hooking up the whole API will take hours.
- azangru 4y agoI just wanted to say, among all the negativity in the comments, that I love RxJS, and fell in love with it after Jafar's workshop. As Ben Lesh often says, there are sadly a lot of misconceptions around Rxjs and the Observable type. The Observable type is a primitive so useful that it keeps getting reinvented over and over (React's useEffect is a weird React-only observable; a redux store is an observable); whereas Rx is a set of convenience functions to help with the use of the Observable type. If people are happy to use lodash, I can't understand what makes them so unhappy about Rx, which is like lodash, but for async collections.
- toastal 4y agoTotally agreed. Coworkers will hate you if you start mixing in these styles into an existing code base. If you want to do FP, go switch languages (and likely jobs/teams) to something where the ergonomic are clear, concise, and idomatic—then the benefits become more obvious. It's a bit like teaching object-orientation through OCaml… just because you can, doesn't mean the community recommends it generally.
- tmountain 4y agoI love FP, but I wouldn’t let someone introduce these abstractions into our JavaScript code base, as they ramp up the complexity in understanding code that can be represented in a simpler fashion with the same results.
- toastal 4y agoA loop isn't simpler than recursion or high-order functions since it introduces state and is noisy, but most examples of JavaScript/TypeScript + FP involve heavy usage of utility libraries that aren't community standards (like a Prelude). Not to say these libraries aren't valuable or of good quality, but it's a lot to learn atop the language itself for a new hire and can lead to some library lock-in as said functions will end up all over the code. The folks that preach the libraries the most are the ones that usually want their JS/TS to look like Haskell which ends up making it impossible for outsiders to follow (so now I need to know JavaScript + TypeScript + Haskell + the weird esoteric version these people write?). And those folks should be allowed and encourage to just write some ML-flavor-to-JavaScript code instead which can often be easier to for a new hire to follow since all examples will follow community standards (wouldn't be surprised if the coders were happier writing it too).
- agentultra 4y agoJavascript is a multi-paradigm language as are most others people are mentioning in these threads. It shows in the specification for the language too: higher-order functions, anonymous functions, Array.map/filter/reduce, etc. Like it or not the language has facilities to enable programming in a functional style. There are advantages to this approach like enabling different styles when appropriate. There are disadvantages as well: you rely on the discipline of the programmers or tools to catch mistakes. But there's nothing inherently wrong about thinking of programs in terms of FP ideas. There are other ways to think about programming than in terms of program counters, control flow statements, and procedures. It's not even idiomatic Javascript to write code that way! JS is a more functional language than most people seem to think. The tragic thing about TFA is that it's not an article but a chapter in a long series of posts and this is just one step along the way to showing how an FP style can manage the complexities of a non-trivially large JS code base.
- borbulon 4y ago> ends up becoming an obfuscated mess of wrapper functions and custom control flow This right here is the reason I don't like pure functional programming. Any engineer should be able to pick up your code and understand it pretty close to immediately. And with pure FP, even when they understand functional programming, they end up wasting valuable time tracking down what it is you're trying to do. * I guess I need to edit to say I mean pure FP in a language not explicitly built for pure FP. The article is about implementing in JS, this is what I'm addressing.
- valenterry 4y ago> Any engineer should be able to pick up your code and understand it pretty close to immediately. So a webdev should almost immediately pick up a mix of C++ and assembly? No. There's a reason we specialize. That is not a good argument against functional programming.
- borbulon 4y agoYou're hitting a strawman here. I shouldn't have to explicitly say that I meant someone with at least some experience in the language you happen to be writing in.
- Verdex 4y agoI'm not convinced that previous poster was hitting a strawman. Your argument (if I understand correctly) is that given some language (here javascript) that one ought not program in such a way that other people who use that language are incapable of understanding it. This example of FP involves a bunch of junk that makes javascript incomprehensible to javascriptors therefore it's bad. Now, previous poster replies with "Hey not everyone understands c++ and assembly ..." and this does sort of sound like a strawman, however we can extract the core argument as "there exist things which you haven't seen before which you don't understand, but that doesn't make them bad" and that does not sound like a strawman. That sounds like a legit argument. For example, perhaps there exists a library which performs some domain specific task using FFT, linear algebra, and distributed computing load balancer algorithms. All of it in javascript. An arbitrary javascript developer is probably not going to be able to understand what's going on. However, that wouldn't be a legit argument against FFT, linear algebra, or distributed computing load balancing algorithms. Specializations exist. Pure FP in javascript might not be a great idea, but it possibly confusing someone who otherwise knows javascript doesn't feel like a real argument against it to me.
- nailer 4y agoOr post ES2017, without all the .then()s: const doThing = async (url, fallback) => { try { const response = await fetch(url) const notifications = await response.json() return notifications.map((notification) => ({ ...notification, readableDate: new Date(notification.date * SECONDS).toGMTString(), message: notification.message.replace(/</g, '<'), sender: `https://example.com/users/${notification.username}`, source: `https://example.com/${notification.sourceType}/${notification.sourceId}`, icon: `https://example.com/assets/icons/${notification.sourceType}-small.svg`, })) } catch (error) { console.log(error.message); return fallback } }
- still_grokking 4y agoIs this code really equivalent? Wouldn't it block on the `await` calls, whereas the original code would instantly pass control back to the caller? (Sorry if this question is odd. My JS is a little bit rusted).
- LegionMammal978 4y agoIt's an async arrow function, which means that it returns a `Promise` when called, much like the original code that constructs a `Promise` explicitly. This `Promise` resolves once the function returns.
- still_grokking 4y agoThanks for the prompt answer! I've overlooked the `async` on the first line… My fault. :-|
- 0x445442 4y agoI’m JS illiterate but I think control is returned to the main thread until the await call returns, at which time the execution continues.
- still_grokking 4y ago
- still_grokking 4y agoFP is the best thing since sliced bread, don't get me wrong! But the seemingly arising "Haskell religion" is at least as mislead as the OOP-religion that held mainstream in stranglehold for a long time. Haskell's syntax isn't anything to imitate. It's hostile to IDE features, at least. Alone that should make it a no-go. The next thing is that Haskell's features may make sense in the Haskell context, but they don't make any sense at all in almost any other language. When you don't have strong types, no lazy evaluation by default, and it's not mandatory to use IO-wrappers, it makes not sense to mimic solutions that arose out necessities that are again results of constrains of Haskell's feature design. You need to do some things in Haskell the Haskell way because Haskell is the way it is. In a different language the chosen solutions are at best bonkers (even they may make sense for Haskell). As always: It's a terrible idea to start doing something because "it's cool" and the "new hot shit", without actually understanding why exactly things are (or should be) done the way they are. The "Haskell religion" is by now imho already mostly only cargo cult… The more worrisome part is that it seems it attracts more and more acolytes. This will end up badly. It will likely kill the good ideas behind FP and only leave a hull of religious customs that the cult followers will insist on; exactly like it happened to OOP in the past. That's my personal opinion, speaking as a big FP Scala fan.
- misja111 4y ago> But the seemingly arising "Haskell religion" is at least as mislead as the OOP-religion that held mainstream in stranglehold for a long time. I wanted to say the same but you were faster than me. The article reminded me a lot of the design patterns fad in the OOP world: that compulsion to make everything abstract and reusable even if there's no use for it yet. But hey, at some point it might be needed and then it would be great! Of course there are some cases where you really want to be ahead of what might come , e.g. public library api's, but those are rare.
- celeritascelery 4y agoI have heard is said that both OOP and functional design are best applied only about 80% of the time. More than that and you are overfitting the method to things where it applies poorly.
- chris37879 4y agoExactly this. I realized that a lot of how I use objects fits in nicely with FP patterns, but when I started looking into FP "best practices" the number of times the best practice is "Replicate this exact behavior from a 'more functional' language, even though your language has idioms for that" is astounding. I decided I'll just keep programming without side effects, if that's what FP is.
- deleted 4y ago[deleted]
- theptip 4y agoThanks for this. I got the same growing sense of discomfort reading the OP, that decomposing everything into operations makes the code way harder to grok vs. just doing the entire transform in one step. I think the point being made was “each transform could be reusable across your codebase”, but I think for this example you really pay a high comprehensibility cost. And duplicating a few lines of code is often actually the right call, instead of coupling two unrelated bits of code that happen to be saying the same thing right now (but which will plausibly diverge in the future). As a new Rustacean, I do really like Result and Option, but writing idiomatically in your language is really important too.
- briznad 4y agoI read halfway through the article before my eyes glazed over and I could no longer tell whether the post was serious or a joke.
- AtNightWeCode 4y agoThat example is what's called fluent code in OO in combination with the builder pattern. To experience peak builder pattern hell one should look at the Android API.