To me, "functional programming" taken back to origins in Lisp and the lambda calculus is a style of programming that focuses on the composition of functions.
The "purity" element is merely the consequence of this focus: in order to be composable, our functions largely need to be free of side effects, and take and return values as mathematical functions do.
I think the emphasis on function composition also makes for a better, more believable sales pitch, once you take into account first-class functions as values and the kinds of abstractions and patterns they allow. I have a version of this pitch which goes like this:
Imagine a function that, given the right inputs, could produce any output in the known universe. To which you might rightly answer "that's pure nonsense". The sheer volume of internal logic would naturally be more complicated than everything within that universe.
But if that function can itself receive other functions as inputs, then the potential outputs expand almost infinitely.
And indeed, this is why the lambda calculus itself has proved Turing-complete: simply by composing functions within functions in this way, you can literally recreate the whole of computing and mathematics.
In practice though, people have their limits, and the day to day operation of a computer does require occasionally breaking the perfect mathematical puzzle for the sake of getting work done, and the vast majority of languages in existence allow for exactly that. A definition that doesn't allow for them might well be "true" in the "pure" sense of the word, but it's not very useful for people other than mathematicians.
And hell, even the Turing-machine uses mutable state.
Then because those are pretty reasonable language features all the languages that had been written in the late 80s-mid 90s and became popular around 2000 had those features.
So then for a while 'functional' was just sort of way of saying 'not java'.
Now 'functional' seems to mean strong algebraic typing for some reason.
The functional programming paradigm models computation as a relation between sets, and is thus inherently declarative. However, in practice, we often think of functions as imperative, ie you put in an input value and get out an output value, same as with a procedure. From this point of view, the characteristic property of a function is that it has no side-effects. Because of ambiguity of the terms, we call such a function pure, and a language which only has pure functions would be a purely functional language.
However, not all functional languages are pure: A functional language is a language with syntax and semantics which allows the programmer to use the functional paradigm efficiently. Some of the concepts which make using the paradigm feasible include - among others - lambda expressions with lexical closure, higher-order functions, variant types and pattern matching, lazy evaluation, type-inference (in case of statically-typed languages).
This is by no means an authorative list, and a language can very well be functional without providing all or even most of them, but if a language does - ie makes them usable without having to jump through major hoops - their presence is a strong indicator that the language should be considered functional.
[1] https://downloads.haskell.org/~ghc/latest/docs/html/librarie...
[2] http://hackage.haskell.org/package/vector-0.11.0.0/docs/Data...
[3] https://downloads.haskell.org/~ghc/latest/docs/html/librarie...
It's pretty cool; you can use ST to have mutable variables and arrays and such, but the mutable values aren't allowed to escape the ST "context". So you're still guaranteed immutability outside of the ST monad, because the type system locks all mutable values inside the monad.
This is mostly only used in very-high-performance libraries that use algorithms based on array access.
Don't ever be a 'programming language 'x' guy or girl'. Be yourself, know some tools and skills and be prepared to switch those out for whatever works best in that particular application. If you limit yourself to a certain programming language, no matter how great it seems to be today you've built in your own obsolescence.
Better to be a guy or a girl with x years of Haskell experience and a whole bunch of other stuff besides.