Post from Kodumaro.
Don’t believe in programming gurus! Said this, let’s go to some definitions, and then, take a look at the lies they’ve been telling.
Functional programming aims to implement the λ-calculus as a full programming environment.
Functional programming (and λ-calculus) is not about using functions, neither about quitting object orientation.
λ-calculus is about first-class and higher-order functions, and everything as a function. Of course “everything as a function” is a bit dramatic for the programming context (but not impossible), however every other lambda feature is reasonable to be called functional programming.
First-class function is the one which can be used as parameter or set to a slot. First-class as in “first-class citizen”, with all rights.
Higher-order function is that which takes another as parameter, or may return one.
Besides, there are some constraints that define the functional paradigm:
- Pure functions: functions cannot have side effects.
- Recursion: a function might call itself, loading a new stack.
- Tail-call optimisation: the last function call inside a function must replace the current stack. It prevents stack overflow when going into recursions.
- Determinism: the functions must be idempotent, that means, given the same parameters, you shall get the same return, no matter how many times it’s called.
- Immutability: no value can be changed. Once set it’s for good.
- Monoid abstraction: support for type wrappers that manage a binary operation over the wrapped type.
And there are some optional features:
- Non-strictness: a function can be strict or lazily evaluated. On lazy evaluation, functions are named “non-strict” and performed on demand only the strictly necessary parts.
- Typed lambda: functions (and values) can be typed by their structure or signature.
- Free and bound variables: traditionally functions may contain bound (existent only inside the stack) and free variables (got from parent context). Alternatively a functional system may forbid free variables, allowing only bound ones. Then you’ll need a fixpoint combinator for recursion.
- Monads: structures to build up computation sequences by combining sequential building blocks.
Now that we’ve made those definitions clear, let’s talk about the misconceptions spread through the programmer’s communities – mostly by their very gurus.
You’ve probably heard it.
Ruby isn’t a functional programming, just as Python is not. Those are object-oriented imperative languages with one or another functional feature, but not enough to be considered even impure functional.
Julia is an impure functional language indeed, but with a lot of imperative features that disfigure its functional trait.
When a guru says that, you can be sure he’s bullshit.
We’ve seen above what functional programming is about.
The logic programming concepts are quite different from functional programming, and deserve a whole dedicated post about. Briefly, it’s about describing the facts’ domain and querying it.
Erlang’s syntax is strongly inspired on Prolog’s, but even yet functional. Erlang sticks to all functional constraints and uses some logic features to provide some typing, which is a functional feature too – typed lambda, you saw it just above.
Furthermore, Erlang uses the same Prolog’s syntax for defining facts to declare function signatures – not to define facts.
So Erlang isn’t a logic programming language, but a fully functional programming one instead.
There’s so much more about functional programming, and you should get involved. I recommend taking a look at Haskell for fully functional programming (install GHC), Standard ML for impure functional programming (install MLton), Elm for front-end functional applet, and Scala for functional object orientation over JVM (or .NET, or Node.js, or natively).