The problem for me is, all of these awesome features already exist in popular languages like JS and Python.
Then there's the "purity" side of things. For e.g. tutorials for Haskell and Clojure say that "mutation and side effects are not allowed" which makes for a more predictable program. But in my experience, I can totally just re-define variables in the REPL and no one stops me. I don't even get a warning. So I'm not sure if I'm missing something, but so far it doesn't feel so different from writing fancy ES6 syntax.
The last thing is "macros". This one seems to be actually unique to FP languages like Clojure, etc. But is this the only unique feature of FP languages?
Genuinely curious, please help me clear up my understanding. I have so far been following some fun Clojure and Haskell tutorials and these languages are very fun/sleek/logical to write in.
I am just wondering if I could accomplish the same in JS easily without learning whole new languages and ecosystems.
That said, you should also think in terms of "What does JavaScript have that functional programming doesn't?". As a working-stiff programmer, most of the time the problems you're going to encounter are going to be a lot easier and faster to solve if mutating state is available as an option.
Perhaps you are already aware of these resources, but I will never get tired of recommending the following: * FP101x by Mr. Erik Meijer (The course is archived on edx.org but you can work your way through it). * The above is based on the outstanding book by Graham Hutton, Programming in Haskell. * And, if you can afford it in terms of time, a book from Mr. Peter Van Roy, Concepts, Techniques, and Models of Computer Programming. (There is a section devoted to FP).
Last but not least, I do love JavaScript.
Hope that helps.
Then the language itself will also know this and manage memory accordingly.
So if you have array with 1,2,3 and an array with 3,4,5 if you unite the arrays memory can just reference the two array as if they were one instead of creating a new one, because for sure they will never change. Imagine this on very big arrays
In fact, many FP language features have been borrowed by non-FP languages to the point people don't consider them "FP" anymore[0]. (Like JS `.map()` and `.reduce()`. Even Excel macros now support first-class functions[1].)
Three features that would make FP thinking in JS easier:
1. immutable tuples and records[2]
2. pipe operator[3]
3. pattern matching[4]
Major epiphany: According to Grokking Simplicity[5], good functional programming isn't about avoiding impure functions; instead it's about giving extra care to them. Impure functions depend on the time they are called, so they are the most difficult to get right. In the end, the purpose of all software is to cause some type of mutation/effect (flip pixels on a screen, save bits to storage, send email, etc).
"Functional Core, Imperative Shell"[6] is probably the most useful FP concept. It is about pushing mutation/errors/impure functions to the outer edges of your code, so the inner code can focus on the "happy path." Complex business logic lives in the inner core; the outer shell is often simple/branchless so unit tests aren't even needed.
[0]: https://hw.leftium.com/#/item/21280429
[1]: https://hw.leftium.com/#/item/26900419
[2]: https://hw.leftium.com/#/item/23924933
[3]: https://hw.leftium.com/#/item/34454184
[4]: https://hw.leftium.com/#/item/16921652