Hacker News new | past | comments | ask | show | jobs | submit login

I'm sorry but this just seems so hard to read and I feel like it would be even harder to maintain.

I'm currently working in a codebase that pulled a ton of this functional style into javascript and it's overwhelmingly complicated and difficult to follow even for me who has a bit of "functional" programming experience (mostly ocaml).

Maybe I'm just missing something or maybe i'm just dense, but I haven't ever personally seen a situation where the complexity of setting up and using this functional style in javascript has ever been more readable or maintainable than the equivalent "traditional" imperative programming. It's one thing if the language or ecosystem kind of enforces this and gives you a standard set of tools to work from or helps with this style via language constructs, but javascript is not that language.

For the exact example in the article, both the try/catch version and the "nullcheck" version seem much simpler to understand (even if they are admittedly a bit "ugly" looking). And while I get that the author is using a simplistic example to help teach, it really doesn't seem like a more complex example would change things.

Samesies. Worked with a bunch of folks who liked bringing functional patterns into JS when that started to get trendy, and I got it, but I never got it. Like, why. Never felt like it was making my life easier.

When I've felt the best writing JS was back when it was a much worse language (which is saying something) and I wrote it about as close to C as I could manage. But then I've always thought the prototypal object model is a giant footgun with little legitimate purpose and any "clever" use of it's simply a bad idea, so maybe I'm just inflexible. I also think modern classes are entirely fine, even good, for Reactjs, and adding more patterns just to be more "functional" (but not really—look under the hood) is a very bad idea, but I seem to be nearly alone in that.

[EDIT] never got why in JS specifically. I get how in a language with proper support for it functional style can be nice. And it's fine in certain narrow cases of course—a little recursive function or simple list processing code, for instance, just not as a broad, principled pattern to apply to as much of a JS codebase as you can manage.

Readable functional programming imo really hinges on some essential basic language primitives. Those are sum types, pattern matching, and restricting mutability.

Forcing sum types onto a language that does not support them is bound to end in awkwardness and reduced readability without providing the real benefits of increased correctness.

This is a great example. std::option from C++ is another one.

Yeah it's really hard to introduce, let alone completely stick with, FP in a non-FP language. I started to introduce some into our Ruby/Rails project, but halfway through, the code was more procedural than functional (which admittedly is more concise and cogent than OO); it's really hard to remember to treat everything as immutable all the time.

Scala's for-comprehensions (and Haskell's do-notation) help quite a lot as well.

Also F#'s computational expressions.

When combined with flow or typescript, Javascript absolutely supports sum types. Also, it's trivial to encode the Option and Either monad using Objects to get the same functionality.

Fully agree. I'm not a JS expert by any means, but I dabble here and there, mainly for work.

If someone did this at work, I'd wonder why they are trying to add so much complexity to something that is rather simple and already well understood by most.

It would be hard to convince me to sign off on a code review where this was added tbh. I'd love to hear how/why I'm wrong here though.

Maybe there are better use cases for it? But in my case, the major thing I care about is that code is simple and readable.

Absolutely agree. This is very clever and it makes the "puzzle" part of my brain happy in the same way writing a program in "OOK!" does.

That said, I work with quite a few juniors. You should absolutely not use this in production.

It could possibly make sense in Typescript, depending on how good generics are.

But, generally, functional programming really shines when you have build-time type enforcement so you're not guessing as to whether things will work together.

In dynamically typed languages, all you know about a function is that its arguments have names and it returns a value. You can have some wonderful free-monads, but you're left to run the code, see it crash, and ponder stack traces or reason through why it failed. (Assuming it's nice enough to fail obviously.)

So you get lured in by how cool it is, but then the moment you use functional techniques beyond what you can fit in your head, you find your tooling gives you no support whatsoever.

A good example of this is automatic currying. In a statically typed language if you pass too few arguments to a function then you get an error message pointing right at the spot of the bug, assuming you have enough type annotations to guide the type inference (which you should).

On the other hand, in a dynamic language if you pass the wrong number of arguments to a curried function the error will only show up when the result of that is called, at which point the stack trace is useless.

Improving the error messages for things like this in the presence of dynamic typing is only possible with lots of help from the language runtime and doing it without ruining performance is still an open research question.

JavaScript does not make it easy. I'm having the same issue as I move towards more functional code in a large React codebase. I'm wanting to adopt more of these patterns but the JS language makes it difficult.

Specifically, JavaScript's lack of infix operators, pattern matching, type classes, and `do` notation make the code harder to read.

Are you required to use JavaScript? Because Reason and PureScript can both hook into React without much trouble and give you the features you want.

I'm evaluating Purescript now. I have concerns about developer ramp up time but other than that I like it.

Reason is more popular but it lacks the category theory centric rigor. The syntax also is not as nice as the Haskell style. I'd rather go with something that fits the FP model better than syntax that is more familiar.

I have to admit, if I ran into this style in a real Javascript codebase, I'd run screaming into the woods.

I've had good success using the Ramda library. It provides a lot of functional style programming helper functions but still feels good in native JS.

But that is almost exactly my issue with it.

Ramda is beautiful and works pretty well in isolation, until you start to use 3rd party code that doesn't work with it well, or you need to interface with non-ramda code in your system, or working with built-in DOM functions or any other number of reasons why you'd need to hop out of the ramda ecosystem.

Then I end up spending most of my time trying to figure out the best way to shove X, Y, and Z into the "ramda way", and often fucking stuff up in the process producing more harder to understand and track down bugs.

Then without perfect buy-in from the entire team, we end up with 3 different ways of filtering exceptions, people using native .map and mixing it with ramda's R.map, uncurrying, reordering, and re-currying functions, and places where the nice control flow is interrupted when it had to dive into 3rd party or native code.

It just ends up hurting every time I go for it, even though the functional style works amazingly in OCaml or Haskell or Rust.

I love ramda and i love fantasy-land but the problem is simply that likely 99% of your colleagues wouldnt understand it. That sucks but is the reality that i often encountered.

I used it also on greenfield projects where I then brought juniors in, and the learning curve for them was hard - at least..

So I kinda avoid it now, though using it taught me much. Even for my embedded C code.

I'm facing the same dilemma, do I go with what junior developers are going to be more familiar with or do I think of it from a 1st principles perspective and build in a way that makes the most sense from a pure engineering perspective. Unfortunately, I don't really see a way to scale past a certain point without these patterns.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact