I must admit that I haven't explored LISP dialects yet, but I was under the impression many of them have side-effects, which would keep them from being considered functional.

<Clutching My Pearls>OH NO SIDE EFFECTS! HOW DARE YOU THREATEN MY FUNCTIONAL PURITY!</Clutching>

If you don't have side effects, all you've got is a gently warming black box. ;)

Seriously - I'd take a look at Clojure - or at least some of Hickey's videos where he talks about the philosophy behind it. And possibly the ones where he trashes type systems and reclaims FP for dynamic languages. You may not agree with him but it's riveting.

FP is a paradigm. Fundamentally, it requires first class functions. Any language with first class functions can be used to program functionally.

Wikipedia, which is a decent proxy for popular opinion and therefore linguistic semantics, would call that functional style, and places functional programming under the mantle of declarative programming, excluding thereby the existance of side-effects in FP. This is my reasoning for saying impure languages are not functional.

But let's avoid further confusion and call them pure and impure for now.

Impure functional programming is not backed by many of the mathematical properties that make pure functional programming easy to reason about.

When I post about FP and what you can do with it, it is referrring exclusively to pure FP.

I would therefore not recommend my readers to learn languages based around impure FP, as that paradigm can be achieved with more popular languages that one might already know, like JS.

I feel that when you refer to 'pure' FP you are referring to languages with a static type system which is checked on compilation. Probably languages with higher-kinded types. This is useful for writing programs in a functional style as it places hard restrictions on what you can write.

A programmer in a dynamic language can write the same program, in the same style, with the same (mathematical) properties - only they will not be checked by the type system. You will have to limit yourself to using the parts of the language which don't mutate - you will need a bit of discipline. This is easier in a language like Scheme which makes it very clear when you're performing a function which mutates a variable.

It's harder these days to find a language that won't support a functional style of programming - even Java now has first class functions - which is why I prefer to refer to it as a paradigm and not a language feature.

Purity is tied to compilation and static typing, almost by necessity. While I have no idea how a pure language that is dynamically typed would look like, it would still have e.g. explicit dependencies to make refactoring easy, whereas a language with side-effects does not.

Scheme which makes it very clear when you're performing a function which mutates a variable

Depending on how this is implemented, you might call it a linear type or monad in disguise. If side effects are explicit they're not really side effects.

You might be able to make a pure functions, if you don't consider type errors to be side effects (which I do if they don't require explicit catching, which is unlikely in a dynamic language), but that doesn't make the entirety of the language pure.
How are you going to represent effects? As you pointed out you will need at some point. Untyped monads? A framework like TEA but error resistant?

So, you might be able to do it, but it's going to be a bit awkward at least, which is why I said "almost by necessity".

Please, let's put aside the denotational debate, because I'm frankly not interested in it, and it is pointless.

That may be, but you have convinced me! I should be stating pure FP specifically, to avoid confusion :-)

When you said "Haskell is bad for FP", what are the concepts you were referring too? And in what way was Haskell bad for them?

I was referring specifically to (primarily statically typed and compiled) purely functional programming. I don't think Haskell has too much influence over impure languages.

If I had to summarize my issues, I would say that Haskell, for a flagship language, strays too far from the core concepts of purely functional programming / typed lambda calculus. It adds complexity (String/Text, typeclasses, lazyness...), reduces certain arguably desirable properties (errors break programs-as-proofs) and it is inflexible in how it represents the imperative world in a functional context, pushing IMO too much coding in IO monads, which is essentially imperative programming.

Because Haskell is, again, the flagship of pure fp, it really shapes the notion of what pure (typed) fp is. I think this may be bad for adoption and innovation.

At this point, though, I should probably write a new post about what I think purely functional programming could / should be.

Haha, ya, I think if you added pure in front of FP for your post title, all confusion would have been avoided, at least for me.

Especially because I think purity is a hurdle for newcomers, and a hard stepping stone. So I find if people start with impure, and gradually of their own learn the benefits of purity and the mechanism to write more and more pure code, it can be a better stepping stone for them moving to a purely FP language like Haskell. It's a more gradual learning curve, I feel.

So I actually thought that this was what you meant also.

I'd actually be really interested in that follow up post you mention. Because my only experience with purely functional languages is Haskell. And I was under the impression that most of the concepts you say bring too much complexity were actually necessary to upheld purity.

For example, without typeclasses, I thought the type system would be a lot weaker, and you'd lose quit a bit of its expressiveness. That without laziness and non-strict evaluation, you were not able to isolate side effects and extract them out of your functions so they evaluate purely. I also thought you couldn't match the performance of impure algorithms without it. And similarly, without Monads and its syntax sugar over them, IO effects couldn't be tracked and controlled by the type system.

Basically, I've always been under the impression that all of Haskell's complexity was due to it trying to maintain purity at all cost.

So I'm intrigued to learn of alternative ways, that could be arguably simpler, yet would still allow for practical, performant and strictly pure code.