7 ms·
I love softcore FP (immutability, first-class functions, etc), but I always get the impression that hardcore FP, like in this article, is about reimplementing p
by BoppreH 4y ago
I love softcore FP (immutability, first-class functions, etc), but I always get the impression that hardcore FP, like in this article, is about reimplementing programming language concepts on top of the actual programming language used.
The pipe feels like a block of restricted statements, `peekErr` and `scan` recreate conditionals, the Maybe monad behaves like a try-catch here, etc.
Of course there are differences, like `map` working on both lists and tasks, as opposed to a naive iteration. That's cool. But this new programming language comes with limitations, like the difficulty in peeking ahead or behind during the list iteration, reusing data between passes, and not to mention the lost tooling, like stack traces and breakpoints.
I've written many (toy) programming languages, the process is exactly like this article. And it feels awesome. But I question the wisdom of presenting all this abstract scaffolding as a viable Javascript solution, as opposed to a Javascripter's introduction to Haskell or Clojure, where this scaffolding is the language.
- michaelcampbell 4y ago> I love softcore FP (immutability, first-class functions, etc), I couldn't come up with a succinct way to say exactly this, since this is very much how I am with it right now. Thanks for that. I will add I'm comfortable with, and prefer, map/select/reduce over for loops where provided.
- philihp 4y agoI've found this too. Once I got comfortable with map/reduce/filter in JS, the thought of using an imperative while or for loop feels as backwards as writing a goto/label.
- bongobingo1 4y agoThe only thing stopping Functional Programming from taking off are functional programmers. It took me years (and Elixir) to get past the "here are some words, some mean what you think, some mean something completely different to what you know, some mean almost the same thing. Also here's 30 overloaded operators that you have to juggle in your head and we wont introduce things like variables for another 4 pages." without running back to something imperative to actually build something. Functional programming's great when you have immutability to drop an entire class of bugs and the mental energy that accompanies that, can pass-around and compose-with small functions easily which makes writing, testing and figuring much simpler and can make your brain click that "its all data" without trying to over complicate it by attaching methods to it. Honestly I think that's 90% of what the royal You needs to understand to get FP and actually try it. Selling people on "its all stateless man" or other ivory tower tripe is such garbage because (as the tutorials always point out) a program with no state is useless, and then the poor shmuck has to learn about monads just to add a key to a map and print something at which point they're asking "how was this better again?"
- BoppreH 4y agoI think that's a bit harsh. It's frustrating to translate an imperative task to an FP language, but it's also frustrating to translate a Bash command into Python, or Prolog semantics into Go, or any program full of mutations and global state into (safe) Rust. I think a lot of the friction you mentioned comes from learning imperative programming first. Our vocabulary, tools, and even requirements come with an implicit imperative assumption. PS: I didn't downvote you, though your tone is harsher than I prefer for HN.
- bongobingo1 4y ago> I think a lot of the friction you mentioned comes from learning imperative programming first. Our vocabulary, tools, and even requirements come with an implicit imperative assumption. Yes that's exactly my point and why no one cares about how great a monad is when trying to learn FP.
- wiseowise 4y agoHow is that a problem of functional programming? When you learn a language you don’t start with “Well in English we say…” you learn language with its idioms and quirks.
- bongobingo1 4y agoIt's not. It's a problem with people trying to sell FP to non FP programmers. A non FP programmer doesn't care about monads. They care about making what they already do simpler and clearer.
- wiseowise 4y agoFair enough. I guess it's the same as when you're trying to teach imperative programming starting from classes and OOP.
- Izkata 4y ago
- disantlor 4y ago"softcore FP" is a great way to put it. JS with Ramda (and an FRP library, if needed) is the sweet spot for me. I use a lot of pipes() but usually don't break them down into smaller functions until there is a reason to; but FP makes it trivial to do so.
- myuzio 4y agoIt looks nice in code, but it's a hell to debug.
- domnantas 4y agoYep, debugging Ramda code is terrible experience. We maintain a service which is making heavy use of Ramda. It seemed like the right tool for the job, because the service is mostly doing data transformation, and the code ends up "clean" and terse. However, we found that onboarding people who are not familiar with FP is time consuming and often people outright refused to learn it. We decided to ditch Ramda, rewrite the service in vanilla JS, prefering immutability where possible. We're about halfway done and it was definitely the right decision. Sure, `R.mapObjIndexed(doSomething, someObject)` is simpler compared to `Object.fromEntries(Object.entries(someObject).map(doSomething))` and now there's a ton of multi-level object spreads, but at least it's simple enough to understand for anyone familiar with JS. We also came up with a `pipe` function that handles Promises. It makes chaining (async) functions very convenient: const pipe = (...functions) => (input) => functions.reduce((chain, currentFunction) => chain.then(currentFunction), Promise.resolve(input));
- daotoad 4y agoI agree 100%. I've worked on some big TypeScript code bases that make heavy use of sort of FP the article promotes; dealing with stack traces and debugging the code is incredibly painful. Jumping around between 47 layers of curried wrapper functions and function composers that manage all state mostly in closures is a real drag. Until the tooling is better, I can't recommend these idioms for real work. TBF, there is a kind of beauty to the approach and as you really dig into it and understand it, it can feel like a revelation. There's something addictive about it. But any feeling of joy is obliterated by the pain of tracing an error in a debugger that isn't equipped to handle the idiom.
- throw10920 4y agoAs a complement to what you said: a far better paradigm to everything-must-be-purely-functional is "write as much of your program as is practical in the functional style, and then for the (hopefully small) remnant, just give it the side-effects and mutation". This leads to fewer errors than the imperative/object-oriented paradigms, and greater development velocity (and quicker developer onboarding, and better tools...) than the 100%-purely-functional strategy. Hopefully, over time, we'll get functional programming techniques that can easily model more and more of real-world problems (while incurring minimal programmer learning curve and cognitive overhead), making that remainder get smaller without extra programmer pain - but we may never eliminate it completely, and that's ok. 100 lines of effectful code is far easier to examine and debug then the entire application, and our job as programmers is generally not to write purely functional code, but to build a software artifact. The above applies to type systems, too, which is why gradual typing is so amazing. Usually 99/.9% of a codebase can be easily statically-typed, while the remaining small fraction contains logic that is complex enough that you have to contort your type system to address it, and in the process break junior's developers' heads - often better to box it, add runtime checks, and carefully manually examine the code then resort to templates or macros parameterized on lifetime variables or something equally eldritch. (and, like the above, hopefully as time goes on we'll get more advanced and easier-to-use type systems to shrink that remainder)
- lupire 4y agoI don't know Clojure, but stack traces and breakpoints are nearly unusable in Haskell also, for exactly the reason you say. It's a weakness of functional programming, not the language. That said, you need these things less when you don't have mutable state and you do have referential integrity so you can zoom in on the critical path of side effecting code.
- still_grokking 4y ago> It's a weakness of functional programming, not the language. I would strongly object this. Have you seen ZIO? https://zio.dev/ https://zio.dev/
- fho 4y agoHmm ... What's your problem with ghci debugging? Iirc it does not work worse then eg pdb. The only problem I encountered regularly was that bugs did only manifest in the optimized versions not in the debugged ones.
- lmm 4y agoI think that's sort of true; to me a lot of the value of fancier and FP is that you can do things "in userspace", with plain values and functions, rather than needing magical language keywords. Magical language keywords do have some advantages because they can have tight integration with the language implementation, like stack traces as you mention. But they're also hard to understand and reason about, especially when it comes to how they interact with each other. (E.g. in languages that have both builtin async and builtin exceptions, the interaction between the two tends to be complex and confusing; whereas where async and error handling are implemented by libraries, it's easy to see exactly what's happening in any scenario, since it all just follows the normal rules of the language).
- fulafel 4y agoFWIW stack traces and break points work fine in Clojure. See eg https://calva.io/debugger/ https://calva.io/debugger/ for some animated gifs showing this in action. (Without tooling the stack traces can be noisy.. but that's incidental in this discussion context)
- BoppreH 4y agoSorry, I wouldn't dream to imply that Clojure is inferior to Javascript. My dig was at the article's implementation of half of Clojure[1], which does have tooling problems. [1] https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule