I would argue that functional code is much closer to Unix pipelines than imperative code. Each function takes inputs and transforms them. Pipelines are just function composition.
100% agree with everything else you just said though.
I'm glad I'm not the only one who thought this. When I first learned about function composition, a supposedly groundbreaking feature of functional programming, Unix pipes were the first thing that popped into my head, but making that comparison out loud was only met with facepalms and accusations of trolling. But it's literally 'take this input and apply these functions to it, in this order'.
Yah, I was expecting this comment. I'd agree but I see nowadays to obsession on abstract issues around functional programming like clojures, monads, recursion and code is data and function as first class citizens which might be of theoretical interest, but quite often are only code obfuscating technics.
When you use (progn ....) in lisp or (do ...) or (-> ...) in clojure you are pretty near to what I understand as imperative but you are leaving the orthodoxy of functional programming.
What is relevant is idempotence which is easily achievable in functional programming and in procedural/imperative as long as you don't use global variables.
Idempotence generally not a feature of OOP. (OOP quite often is not even deterministic).
While a lot of the type theory stuff is controversial, closures and recursion are core concepts of functional programming. I mean, they date back to the first ever functional language, lisp. Removing them would be like removing classes in an OOP language.
100% agree with everything else you just said though.