There is the Lisp/dynamic typing (Scheme, Clojure, Erlang, Elixir, Julia...) style:
Avoiding state from a correctness perspective is a basis but not necessarily the end-goal here.
The primary goals are to decrease complexity and coupling and increasing malleability, composability and empowering through interactive development (REPL).
And the statically typed (Haskell, OCaml, Scala, F#...) one:
Here there is a much stronger focus on internal consistency of programs, which enables stronger mathematical soundness and reasoning.
Note that this distinction is only in part equal to the general dynamic vs static one. Typing discipline is not completely orthogonal to the paradigm (for example imperative vs functional).
I personally am very much in the camp of the former and only have superficial understanding of the latter.
I always recommend SICP because it was the book that helped me 'get it'. But there might be more modern alternatives.
A question you can ask yourself: How do you approach programming?
- Your program design is usually very high level. A graph of ideas. Then you want to interactively and iteratively discover requirements and check assumptions. You strive for simplicity and want to gradually achieve robustness, only where needed.
- You think in terms of laying out rules and form. You want to infer the connections and implementations given those rules. You gain satisfaction from solving puzzles upfront to enable strong run-time guarantees and sound abstractions.
If you lean stronger towards one of these thinking models then you might consider diving deeper into its respective typing discipline.
Or try ocaml https://www.cs.cornell.edu/courses/cs3110/2020sp/textbook/
Nesting functions provided a necessary structure that both includes containment and reference. At the time JavaScript did not have block scope, modules, or native classes. Also taking advantage of lexical scope in favor of prototypes/inheritance resulted in slightly faster execution. Really, for me, it was more about taking full advantage of lexical scope more than concern for what the function returned as a value.
I would see other people attempt to fake classes in the language and it was atrocious. First of all the code was ugly, but worse is that there absolutely no benefit to this. Clearly these other developers were just just trying to mimic some conventions they use in other languages without learning how to organize their code. That is the opposite of elegant and I didn’t want anything to do with it.
An Introduction to Functional Programming Through Lambda Calculus
Book by Greg Michaelson
It's amazing it was published 31 years ago (1989) which shows that it's a timeless book to read.
This has been referenced from discussions a couple of times:
https://news.ycombinator.com/item?id=6093386
https://news.ycombinator.com/item?id=3851352
https://news.ycombinator.com/item?id=11578961
https://news.ycombinator.com/item?id=10714770
https://news.ycombinator.com/item?id=773369
https://news.ycombinator.com/item?id=16973546
https://news.ycombinator.com/item?id=14395620
https://news.ycombinator.com/item?id=13211603
To quote a SO answer on why learn lambda calculus[0]:
If you want to program in any functional programming language, it's essential. I mean, how useful is it to know about Turing machines? Well, if you write C, the language paradigm is quite close to Turing machines -- you have an instruction pointer and a current instruction, and the machine takes some action in the current state, and then ambles along to the next instruction.
In a functional language, you simply can't think like that -- that's not the language paradigm. You have to think back to lambda calculus, and how terms are evaluated there. It will be much harder for you to be effective in a functional language if you don't know lambda calculus.
[0] - https://stackoverflow.com/questions/114581/how-helpful-is-kn...
It's easy enough to pick up in an evening and explains it very well. It's behind a paywall but there's a free trial.
These days I would recommend Elixir, if you want to a hang of untyped FP.