True, the conceptual difference of (pure) functional and imperative programming is disguised by the many functional patterns most mainstream languages have absorbed. While these patterns are useful, there is more to say about pure functional programming.
I recently gave a talk to some colleagues about that, which was divided into two parts: Practical functional programming patterns we can use today in our codebases (we use mainly C++, Python) and a more abstract part about pure functional programming.
The first part basically boils down to using functions as first class "objects", while the point of the second part was, that there can't be implicit state in pure functional language.
The consequence of that is, that there is no strict order of execution, which is in direct contrast to imperative programming, which is all about list of statements, that are executed one after another.
I presented small code examples in Haskell and showed corresponding execution graphs to emphasise, that the compiler can easily optimise the execution order.
I like that POV, because it clearly distinguishes imperative from functional programming. Starting from there, it's also easy to understand the motivation behind monads or elaborate on architectural patterns like " functional core, imperatively shell".
When you execute a function in a mainstream languages, the arguments are usually evaluated first, then the function is called with the result of that evaluation.
E.g. the following in JS will always print the confirm message. But in a lazy language like Haskell, as the x parameter is never used, it'll never be printed.
(function(x) { return "bar"; })(confirm("foo"));
This can help with implementing things like infinite streams (e.g. iterate[0] in Haskell), which may be a pleasant patterns to solve some problems sometimes. On this example alone, I wouldn't qualify it as highly relevant for day-to-day work, but there may be more interesting use cases I'm not familiar with (I'd guess there might be interesting side-effects in concurrent settings).
I recently gave a talk to some colleagues about that, which was divided into two parts: Practical functional programming patterns we can use today in our codebases (we use mainly C++, Python) and a more abstract part about pure functional programming.
The first part basically boils down to using functions as first class "objects", while the point of the second part was, that there can't be implicit state in pure functional language. The consequence of that is, that there is no strict order of execution, which is in direct contrast to imperative programming, which is all about list of statements, that are executed one after another.
I presented small code examples in Haskell and showed corresponding execution graphs to emphasise, that the compiler can easily optimise the execution order.
I like that POV, because it clearly distinguishes imperative from functional programming. Starting from there, it's also easy to understand the motivation behind monads or elaborate on architectural patterns like " functional core, imperatively shell".