1. Don't use globals. Zero global variables should be the goal, that way, you avoid "spooky action at a distance" where some code here changes a global that changes the behavior of code over there. A function that avoids global variables is easier to deal with than one that doesn't. If you feel you need to use a global, think about why you need one before adding it. Maybe you can avoid it.
2. Parameters to functions are immutable. That way, you won't have to worry about data changing during a function call. If the parameter can be mutated, can you signal the intent in the function name or signature, so the programmer knows that to expect? Generally, try to avoid changing parameters in a function.
3. Separate I/O from processing. Do input, do your processing, then output. God, I wish the major component I worked on did that (concurrent DB requests)---it would make testing the business logic so much easier as it can be tested independently from the I/O.
Those three things can be done in any language, and just by doing those three things, you can most of the benefit of FP without the mathematical jargon (Monads? How do they work?). There's no need for over-engineered code, and you can be as explicit as you like while keeping the cognitive aspects to a minimum.
> “Of course!” Joe thinks. “It’s all so simple now. The key to understanding monads is that they are Like Burritos. If only I had thought of this before!” The problem, of course, is that if Joe HAD thought of this before, it wouldn’t have helped: the week of struggling through details was a necessary and integral part of forming Joe’s Burrito intuition, not a sad consequence of his failure to hit upon the idea sooner.
TL;DR There’s no beautiful explanation that will help you understand, you need to get your hands dirty with code.
For example, the Maybe monad has no state. It sequences operations that can fail. The Error monad aborts the computation and returns an error. Similarly, Min, Max, Product, Sum, Dual don't have an state.
Code readability should be the top most priority when writing code. Even more than portability and performance.
Anyone can rewrite a piece of good, succinct, clear code. Even if its performance is poor.
That cannot be said for clever hacker code that -was- fast until business requirements changed over time and now the guy that used to understand the code is long gone.
1. Don't use globals. Zero global variables should be the goal, that way, you avoid "spooky action at a distance" where some code here changes a global that changes the behavior of code over there. A function that avoids global variables is easier to deal with than one that doesn't. If you feel you need to use a global, think about why you need one before adding it. Maybe you can avoid it.
2. Parameters to functions are immutable. That way, you won't have to worry about data changing during a function call. If the parameter can be mutated, can you signal the intent in the function name or signature, so the programmer knows that to expect? Generally, try to avoid changing parameters in a function.
3. Separate I/O from processing. Do input, do your processing, then output. God, I wish the major component I worked on did that (concurrent DB requests)---it would make testing the business logic so much easier as it can be tested independently from the I/O.
Those three things can be done in any language, and just by doing those three things, you can most of the benefit of FP without the mathematical jargon (Monads? How do they work?). There's no need for over-engineered code, and you can be as explicit as you like while keeping the cognitive aspects to a minimum.