back
86 comments
Every time I read articles about functional programming, I feel like I’m being talked down to. There is always an air of condescension, which, honestly, makes the content hard to get through. This article uses a lot of this type of language calling one way of doing something “insane”. He says things like “dirty nappy” and “or just get rid of it”.

If functional programming is so great, it should be able to stand on its own merits without the constant insults thrown at other programming paradigms.

I lean more towards FP than OOP but there are times when each paradigm makes sense in a specific situation (especially because we rely on a lot of third party code we can’t control).

> Who on earth would craft such a ghastly abomination?

> It may come as a surprise to hear that we can write full, everyday applications along the lines of the functional analog above.

> It is obnoxiously verbose and, as it happens, bad practice

> I avoid using this like a dirty nappy. There's really no need when writing functional code.

> If you are the micro-optimization sort, please close this book. If you cannot get your money back, perhaps you can exchange it for something more fiddly.

To be fair, the later chapters are much more focused solely on FP without the disparaging comments toward OOP.

IMO the author was just attempting to make his text engaging and approachable, but people have personalities, and some personality quirks can rub certain people the wrong way.

There is no shortage of drier materials on the subject!

I've written a lot of tutorial material. Not sure if that qualifies me to comment here but... One aspect of my personality is that I'm a snarky cynical bastard who loves to confront perceived flaws in things via jokes.

So how does this come across in my tutorial writing?

Not at all. That part of my personality is completely absent (I hope) from anything I create that is intended to teach people. Because the people I want to teach programming to could be anybody. They could be someone who can barely speak English and will just be totally confused by snark. They could be a precocious ten year old whom I would rather not expose to my adult cynicism. They'll get enough of it in life anyway.

Teaching materials should be clear, cynicism and snark free, and should never be condescending to either the reader or any alternative technology or point of view. That doesn't mean criticism free. But the criticism should feel balanced. Does comparing the alternative with a dirty nappy feel balanced to you?

For a critical view of all programming paradigms see: https://www.info.ucl.ac.be/~pvr/book.html (late drafts are available online).

A summary is available in: https://www.info.ucl.ac.be/~pvr/VanRoyChapter.pdf

One of the running themes is the paradigm paradox: "More is not better (or worse) than less, just different".

In other words, each paradigm has its own distinct advantages, which are discussed both in practical terms and using formal semantics.

> Every time I read articles about functional programming, I feel like I’m being talked down to.

I don't. There are lots of good functional programming resources where the author is polite and civil. Being condescendent is not an attribute of functional programming.

Example: https://fsharpforfunandprofit.com/

Have you tried reading "Can programming be liberated from the von Neumann style?: a functional style and its algebra of programs" by Backus?

https://dl.acm.org/doi/10.1145/359576.359579

I really, really hate the way this author writes. It's so needlessly verbose, obtuse, and condescending.

I've written Node for a living. Mostly Typescript in recent years. I've encountered multiple codebases where previous developers have used all kinds of novel constructs to make Javascript codebases resemble a purely functional language. I've never seen an example of this where the developer has actually managed to make their codebase more concise, understandable, testable, extensible, or more robust. The usual outcome is a complete birds-nest of spaghetti code that only the original developer could ever understand. These codebases usually never outlive the tenure of the original developer: They're usually thrown out the second another dev even lays eyes on it.

Reading through this article, I don't really see anything that would make my real-world coding job easier. I don't see any constructs that would actually make my code less complicated. Not to mention the elephant in the room that adding thousands of lines of scaffolding code (that only the author understands) so that Javascript supports monads (that the developers asked to maintain the code won't understand) adds so much more surface area for bugs. If you want to write an application in Haskell, just do that instead. At least then the company knows to look for a Haskell developer to maintain the mess you've made.

I completely understand where you are coming from and don't doubt that you've seen some gross things built in the name of "functional Node". I do think that functional JS can be elegant when applied with restraint.

I've really enjoyed creating functional pipelines with Ramda in the past for professional projects. I liked how I could use the Ramda functions to explicitly state in my code what the flow of data was with functions like pipe and converge. It seemed to me that being able to understand the dataflow was easier with this paradigm. I could even create pipelines that would automate away dealing with promises in my pipelines with pipeWith. I would implement the same bits of code in "vanilla" js and with Ramda and Ramda was more concise and easier to read (if you understood how Ramda worked...).

You can see an example of the style that I like here: https://github.com/chughes87/calendarbot. I definitely was more "clever" in parts of that codebase than I let myself be in a professional setting heh.

I successfully onboarded a different team onto one of my projects when I was being switched to a different product at my company. An engineer who later did some maintenance work on it told me that the codebase was simple and easy to work with. I did get complaints about a later project that I implemented with Ramda from a person who was totally uninitiated and didn't bother to ask me for help..

I made a lil presentation about Ramda that explains some of this with some graphics that I think are helpful: https://docs.google.com/presentation/d/1tmre_8qJP-QhakXbiBpZ...

I got the impression that the reason the author chose JavaScript was not necessarily with the intention that people would go full-bore FP with it, but more as a way of "meeting people where they are"; JavaScript is widespread and many people are already familiar with it, so it's more likely that they can get up and running with the examples and start exploring the concepts more quickly than with, say, "Learn You A Haskell For Great Good" (where, at the very least, a lot of people would need to download and install the compiler).

And, if the author is successful, then the chances that you could one day be able to write JavaScript code in this fashion and expect it to be maintainable would increase!

This is exactly my impression as well and my personal experience. I first felt like I really understood functional programming when I started using Ramda. It was a library that provided me functional tools in a language I was already familiar with and that allowed me to play around freely without friction.
I've never seen an example of this where the developer has actually managed to make their codebase more concise, understandable, testable, extensible, or more robust.

This is almost purely functional but makes no attempt to look like anything other than JavaScript and just about everything is identifiable to profilers and covered by some form of test automation.

https://github.com/prettydiff/share-file-systems

The first bits of code I come across on this codebase isn't functional: https://github.com/prettydiff/share-file-systems/blob/master.... You're modifying state. You're implementing iteration with do..while loops. That doesn't scream functional to me. Iteration is done with things like Array.map, Array.filter, Array.reduce in functional JS. Higher order functions are key. Functional code is declarative. do..while is imperative.
I wish the standard language in the browser was statically typed, immutable data, and purely functional. Not what we have, which is a language that is not only OO, but a crazy version of it, that "can" also be used quasi-functionally.

There's a lot more to developing large projects than your own code. What about the ecosystem? What about everyone else's code? JS IMHO is just a complete mess. That's not at all to belittle the size of the problems it is tasked with solving, which are hard and complex. The difficulty is precisely why the right tool for the job is something that really insists on some level of correctness, in the vein of what rust tries to do at the systems level.

This is all IMHO and there's a lot of room for different opinions here, but I'm guessing we have a consensus, even among JS's biggest advocates, that it can't be described as "insisting on correctness".

Unfortunately the more relevant follow-up question might be: okay it's the wrong tool for the job, so what? It's what we have.

You can learn Elm. All twelve of us will help you.

It's far from being "the standard language for the browser", but the browser doesn't know that.

Can it really be called the wrong tool when so many huge businesses and essentially the entire globe are powered by it? It’s certainly worked imo
I think its functional parts are some of its best qualities. Even before we got let and const, function scope was a really nice treat that many many other languages from around the same time got wrong(er)

what I really detest about javascript is its inability to say no to the programmer (most dominantly typing woes), and how incredibly late it got some super basic features for code organization. private class members (in a way that isn't syntactically insane) got added to the language figuratively two days ago. what the hell?

> This is all IMHO and there's a lot of room for different opinions here, but I'm guessing we have a consensus, even among JS's biggest advocates, that it can't be described as "insisting on correctness".

this was pretty much the result of the XHTML debacle as well, and I know the reasons why that went down the way it did, but it's kind of weird to me that We Just Can't Have Enforced Correctness In The Browser.

Please use PureScript with us and lead a happy life
When JS was made, Andreesen wanted to implement Scheme but his boss asked him to make it look like Java.

Is it crazy? yeah. But it’s not quasi functional.

I've used this guide as a reference and now feel pretty good with a lot of FP concepts and why they exist - pure functions, monads vs applicative vs functors, referential transparency etc

It's easy to understand Lists, Options, Eithers and all the other classic monads and what they do. It's harder to understand other forms this can take.

At work I had to build something that ended up leading to creating a new monad type[0]. That process crystalized why we ended up with these ideas and structures much more clearly.

I also highly recommend any of Scott Wlaschin's videos[1]. He does a great job conveying FP ideas, and his videos introduced me to F# which is a really fun language with a very clean syntax.

Another great blog is by James Sinclair [2] who similarly has several articles on using FP in a practical way though some of the code can get a little deep but in an interesting way.

Loosely coupled but cohesive is a very useful mantra when integrating FP ideas along with keeping everything very simple - avoid crazy compositions, deeply nested types, etc. Just cause something can be abstracted due to FP (composing a bunch of function calls, looping once instead of 3 times etc) doesn't mean you should. There is value in breaking pieces up.

[0] https://sambernheim.com/blog/building-a-monad

[1] https://www.google.com/search?client=safari&rls=en&q=scott+w...

[2] https://jrsinclair.com/web-development/

> Chapter 04: Currying

Allowing a chain of fat arrows and parentheses-free parameters was one of the nicer choices they made for ergonomic functional programming — being able to concisely write:

const add = x => y => x + y;

Ends up looking similar to Haskell type signatures.

The big missing FP features in ECMAScript are pattern matching and pipe operator.

I know there are proposals but neither seems to be making much progress.

I like FP but shoehorning it in with libraries is ugly compared to having native syntax.

Both are active tc39 proposals :)

https://github.com/tc39/proposal-pipeline-operator - Stage 2

https://github.com/tc39/proposal-pattern-matching - Stage 1

Hopefully we get both in the next couple of years.

I’ve been watching them for years! I’m getting impatient.
Expression-orientation would be my #1 request (for both code blocks and switch statements). If that came with pattern matching then even better. A pipe operator would be a nice to have but isn't crucial IMO.
While it isn't mainstream, I encourage people to look into https://scala-js.org, I can't find any more practical language where you can take advantages of FP + the js ecosystem.
Anyone know if Record & Tuple (deeply immutable primitive values) is moving ahead or stalled?

https://tc39.es/proposal-record-tuple/tutorial/

Have needed to get people working on Scala code at work, and introducing the concepts in JS first is the right approach for most junior devs, I think. Existing familiarity with the lang is one thing of course, but it's also so nice to just pop open a console in the web browser and just talk through concepts without fretting over jdk versions and sbt and whatever.

Multiple colleagues swear by this book in particular, but I don't know if it needs to be read cover to cover. Reassuringly enough, much of the foundational content regarding immutability and higher order functions seems like it is already common knowledge to younger devs.

I think the biggest conceptual leap from the FP lite that is already practiced in modern JS to the "hard FP" of Haskell and Scala is the generalized approach to contexts via functors/monads. Luckily one such context already exists in JS in the form of the list. Implementing Option/Maybe using a single item list, and composing operations using the existing map and flatMap methods is a nice exercise that paves the way to the happy path only style of programming of the more advanced langs.

This is less a guide on how to do fp in Javascript, and more of a tutorial on how to implement a pure-functional-programming language in Javascript.

Javascript can do some functional programming, but it's not Haskell or OCaml. If you try to use it like that it quickly becomes a big mess and one that is not performant at all. You want to do pure, functional programming? Then write Haskell, or Elm, or Purescript.

I'm saying this as someone that loves fp, but is trying to get rid of a considerable chunk of fp-ts on a big codebase at work.

As a wise man once said, don't fight the language. Doing this deviates from Javascript semantics. It's a hack that is not actually helping people learn fp.

Also, please, don't do monads in Javascript! Monads are a solution for pure languages to deal with effects. Javascript can just do effects as it is!

I'm quite happy with javascript as it is but I understand you might prefer other languages.

I haven't had occasion to use wasm but it seems that it provides the ability to run most (all?) languages in the browser.

Here, for example, is f# wasm.

https://fsbolero.io/

Your point touches on the hardest part of solving the problem. Even if we could all agree that JS needs to be replaced, which of course we can't, and we had a perfect ideal replacement that we all agreed upon, that already works -- what about the ecosystem? All the tutorials, videos, articles helping newcomers, all the libraries, linters, IDE integrations, build tools, etc.

The only way I can see the problem (assuming someone agrees it is) of JS getting solved is if something comes along that's so amazing and blows it out of the water so hard that adoption explodes and browsers start natively migrating to it, along the lines of what we've seen with TypeScript, but instead of a bandaid a full replacement.

todo app has always been the least inspiring demo that has ever existed.

Are there any wasm demos (not necessarily source code) to try that would blow my mind? Genuinely interested. Maybe I have seen dozens and it's not obvious.

Nice! This looks great for experienced programmers. I also wrote functional programming JavaScript lessons, only mine are meant for beginners and don't place an emphasis on comparing FP to other paradigms, but rather treating programming in FP from first principles as an intuitive approach.

https://intuitivejs.info/

Probably its time somebody wrote something that could be titled 'The Unreasonable Effectiveness of JavaScript' - the language has of course been wildly successful, if measured in terms of adoption at any rate, and it might be good to try to understand why (beyond 'it's on every browser, dummy').

Enjoy:

- record and array literals

- arrow syntax for lambdas

- spread operator

- map, reduce, forEach

- string template literals

- default values with ||

- single thread memory model

- all the pretty colours

Avoid:

- Formal OO constructs, i.e. 'class' and whatever goes on inside it. They feel out of place, and e.g. the this.function() syntax is clanky. Special hate reserved for those magic proxy getters - breaks the simple record model.

- Formal typing, i.e. Typescript. Becomes unnecessarily verbose and boilerplated, tooling is not quite there, and you almost always need to poke holes in the type system to do anything interesting anyway.

- Lodash and friends. Not needed now the core language has so much out the box.

Where Javascript seems to shine is in being a simple, functional language, with concise syntax, and without heavy OO or type formalisms.

You lost me at avoid formal typing and lodash.

At least to me, Lodash is absolutely necessary even in new projects — such a wealth of functionality and most of it isn’t available OOB in the standard library. It’s easily tree shakable as well.

As for formal typing, TypeScript was a boon for my productivity. Curious about any examples of use where it’s been inadequate?

Using abbrevations for something that is not common knowledge is a way to shut out people from discussion IMO - change my mind.
Who is this IMO?
I agree in principle, but I'd figure most people on HN would know what FP and OOP are.
For the last few years, my biggest problem with JS is mutability. I often catch myself spending unreasonable amount of time trying to prevent mutability. Due OCD, mostly.

TS is helping somewhat but it compiles down to JS, and well, almost anything can happen at runtime.

Haskell compiles to assembly language where every instruction is procedural and every register and memory location are mutable.

“Compiles to JS” doesn’t imply anything about what a language has to look like; see PureScript for example.

Reading over many of the comments here makes me sad.

Many of them seem to be about what I, the developer, can use.

Let me reframe it — what if you thought of FP techniques as something you could expose to a user of your API?

What if you viewed all your work in a language as a language. Borrowing concepts like affine types (aha, rust!), dependent types (hello, Agda!), composition (from pipes to combinators, this one is everywhere!) is important.

Strictly procedural or OO concepts might be useful in an implementation, but it rarely helps the user.

Some people here are feeling put off by an author pointing out bad practice.

Some people writing security vulnerabilities in C are feeling put off by a programming language with sanity checks.

I am grateful whenever someone takes its time to show other ways to get things done. Using those techniques is optional, but at least I know they exist.

One's toolbelt doesn't ever have enough tools.

All the *.md links give a 404.