That's what I was wondering as a woefully uninformed armchair warrior burnout.

The main (only?) difference between functional and imperative programming is mutability. The ideal FP representation is a spreadsheet with no infinitely cyclical references to cells like A1->B1->C1->A1, and the ideal IP representation is a Turing tape reading/writing/moving with no registers. I'm probably wrong about both of these, but that's how I think of them.

So most IP languages like JavaScript eventually reach a state complexity limit where humans can no longer analyze them. It's like trying to remember more than 7 digits in a phone number while someone is yelling more phone numbers at you.

Whereas FP languages work more like piping STDIN/STDOUT/STDERR streams between executables running in isolated processes, and have no scalability limit. We just don't have the hardware to properly run them, because we went the SIMD/GPU route instead of CPU clusters.

Note that most of the FP lingo like currying, closures, lazy evaluation, etc are clever and have their applications, but distract from the core essence separating it from IP.

People a little older than me did a lot of work in the 1990s to move away from mutable state (assembly, C++) and transition to pure functional synchronous blocking deterministic idempotent logic (Lisp, Prolog, VHDL/Verilog, HTTP, etc). Unfortunately corporations unwound most of that progress by reintroducing every anti-pattern in a million-monkeys typing proprietary race for profit. Async/nonblocking code is borrowed from monads and is a workaround for single-threaded code lacking proper scatter-gather arrays and higher order functions that can fork/join other threads.

The only language I know that gets this stuff mostly right is ClojureScript, which attempts to use pure FP by avoiding monads and executing logic as a one-shot process with new input/output passed while suspended waiting for events, similarly to how PHP works. It also has a software transactional memory that works like Redux for storing state, which is also related to copy-on-write arrays in PHP before version 5 introduced pass-by-reference classes and permanently derailed what made it compelling. Haskell and other FP languages mostly miss the point due to their over-reliance on monads and syntactic sugar, which costs them purity and makes them little better than IP languages for use-cases in real life. And of course since ClojureScript is Lisp-based, its parenthesis syntax makes it difficult to read, putting it into the category of write-only languages like Perl, which all but guarantees that it will never reach mainstream adoption.

I'm mostly skeptical of Rust for these reasons. Because a properly structured program doesn't have much/any mutable state, which negates most of the need for the borrow checker. I have a few dozen criteria that I use to judge what a "good" language would look like, and there simply isn't one yet. I would dearly love to write one, but it would take me perhaps 2-5 years, so with just nights and weekends and a few weeks of vacation per year if I'm lucky, that will never happen. The main challenge I face in my daily work is overcoming this condemnation of being forced to work with mediocre tools for the reminder of my life. And I see the 100x overhead cost of poor tooling reflected in the $200/hr wages of programmers whose productivity has fallen so low that a social network is considered a big lift. Whereas if we look at the logic involved, a teenager could write one in a couple of weeks with something like HyperCard/FileMaker/Access.

I'm reminded of the Kirk-Picard conversation that goes "I take it the odds are against us and the situation is grim?" because I've mostly witnessed regression instead of progress the last 25 years. But revolutions happen when things are at their worst, so that keeps me going and inspired.

TL;DR: mutability matters more than cyclomatic complexity.