Interesting; functional programming was introduced to me through dr. racket scheme, and the core concept in there was that there is no mutable state. To me, having mutable state makes it imperative, you're not evaluating functions/expressions, you're executing statements that modify a state.
Yeah, this is one of the reasons why Racket doesn't call itself PLT Scheme anymore. Scheme has procedures `set-car!` `set-cdr!` that allow you to mutate the content and the address register of a pair.
Scheme has pioneered or picked up a lot of advances for making programs more functional, for example lexical scoping, closures, etc. that were not present in every lisp.
What's a bit funny is that I have experience some Schemers sneer at CL for "lacking the functional elegance" and common lispers sneering at Scheme for not being a true lisp with namespacing, etc.
One observation I have is, that in my career I start to see more patterns in code (they were probably there years ago but I wouldn't have recognized them). Sometimes I see monadic patterns in otherwise object-oriented code bases, or I see dependency injection realized in functional, immutable code bases. Maybe it would be time to revive the pattern movement to recompile common patterns and aim at a modern description of these. I feel like a lot could be gained [].
[] Also I'll walk out of any interview were I will be asked again for the visitor pattern. so tired.
Racket originally had mutable cons cells but they got rid of them sometime while it still was called MzScheme. One of the reasons they rebranded to Racket was that they no longer implemented scheme as specified.
As I see it, there are two orthogonal roots to functional programming: Mathematical functions on the one hand, and lambda expressions/closure/higher-order functions/... on the other.
The former implies immutability and technically belongs to the declarative side of things: A mathematical function declares a relation between input and output, but I say technically because functional code can read rather algorithmic.
The latter can be added to imperative languages that do feature mutable state. Depending on the language, I might still classify it as functional, but impure.
yeah, I'd say its quite simple. there is "Functional programming", and it is an umbrella term. Then there is "purely functional programming" and it's kind of better defined than it's hypernym. For purely functional programming we are certain that we want to be immutable, try to limit the usage of effects.
Lately, I think, there is even a de-emphasis in _functions_ as the base of (purely) functional programming. What's now beimg emphasized is the composability-aspect. Functions are an abstraction that is composable, but so are other abstractions.