Can be used as cheat-sheet or quick reminder of main principles. Main goal of this article is to explain basic concepts of FP in simple words.
Contents:
- Imperative vs declarative
- Basic concepts
- Point-free style
- Composition
- Immutability
- Closure
- Referential transparency, memoization
- Eager vs Lazy evaluation and observables
- Data Structures and operations
Imperative = how; list of instructions how to achieve result.
Declarative = what; only declaration of expected result
Why functional programming? It's provable by math and readable. But remember not go too far with it until you'll be confident in what you're doing.
TODO: explicit vs implicit,
Procedure - collection of operations; In simple words: functions return a value, whereas procedures don't.
Pure functions - functions with no side effects; can't access parameters outside, given same input -> give same output.
Predicate function - function that return true/false result.
You can wrap functions - so impure function will be hidden into pure function
Function with 1 parameter named unary function, with 2 - binary, if more - anyary function.
Point is an input to the function. Point-free style is mapping between parameter and passing function.
Composition - output of one function becomes an input to another.
Pipe - pipe as functional composition.
Lodash has built-in compose()
, pipe()
and much more. Lodash FP docs.
Note: much easier to compose unary functions
Immutability - value cannot be mutated or reassigned.
Note: JS const does not provide value immutability, only immutable bindings.
Object or array can become immutable with Object.freeze()
, but it freezes only top level of the object.
Useful link: Immutable.js
Closure - is when a function "remembers" the variables around it even when that function is executed elsewhere; Closure is a record storing a function together with an environment.
Prevents from being garbage collected.
If function returns another function that makes some calculations -> calculations can be delayed/postponed until they'll become necessary -> leads to lazy algorithms (vs eager).
Referential transparency - function call can be replaced with it's return value and this won't affect program behavior.
Pure function is a function that has referential transparency. Matters when you read and need to trust your code.
Memoize caches the return values of the function, so if the function is called again with the same arguments, Memoize returns the cached value, instead of computing the value again. Only pure functions can be memoized.
Memoization is an example of referential transparency; performance technique.
Useful link: Memoize library
Eager evaluation: run function as soon as it is bound to a variable. Immediate execution.
Lazy evaluation - wait; evaluate only when value of expression is needed.
Lazy array = observable.
Observable - invokable collection of future values or events.
Observer - is a collection of callbacks that knows how to listen to values delivered by the Observable.
Subscription - execution of an Observable.
Use cases: wrap http request into observable, add subscriber and it will be called on demand (e.g. response). Other example are series of values in time (streams, setInterval etc). You can add subscriber to 'push' event and do whatever you need.
Useful link: ReactiveX library, or RxJS - lodash for events
Map - take values, transform and copy them into new DS. Do not change an order and cause no side-effects.
Filter - exclusion function; Return true - keep value, false - remove. Filter code example
Reduce - combining (not reduction) operation; operates on 2 values. Reduce code example
Fusion - take list of operations and compose them into single operation. Optimization technique;
Usage example: you call map several times, map is pure function, so memory usage scales with map calls. Fusion let you combine all operation in one and reduce used memory. Fuse code example
Same as fusion but for different shapes of functions (e.g map+filter+reduce) - shapes aren't compatible