Other Programming Paradigms
Those three paradigms - imperative, object-oriented, and post-functional - are the three that Java 8 supports
nicely. However, there are many other programming paradigms out there, and it is important to know
about some of the dominant ones. Learning new paradigms helps you think about problems in different
ways, which means that you are better at solving your problems. Even more, however, knowing about other
paradigms allows you to have conversations with developers coming from different contexts, which is how
you will avoid intellectual and professional stagnation. There is a kind of stagnation that can creep into a
programmer's life after a few years: familiarity and relative satisfaction with a particular set of tools can
lead to the mistaken impression that those tools (and derivations from them) define the universe. If you are
starting to think that way, here are some ways to shake yourself loose of that trap.
Most of the references to “functional programming” are referring to this paradigm. In this paradigm, the
program is a set of mathematical functions, and the programmer's job is to define and manipulate the
functions themselves. The data that is moving through the application is largely irrelevant: the functions
are defined based on the types and shapes of that data. The particular implementation details of how these
functions are applied are left to the runtime or compiler. I was introduced to the logical/mathematical
paradigm through the programming language OCaml, which is a derivative of MetaLanguage (ML). If you
want to see how well this approach works with concurrency, see the programming language JoCaml, which
is the join calculus (i.e., fork/join) mixed with OCaml. Haskell is probably the current poster child for this
paradigm, and there is a strong case to be made for Erlang, too. This paradigm also includes Mathematica
and other “computer algebra systems,” as well as Coq and other “interactive theorem provers.”
This paradigm works very well when I/O is incidental to the work being done, and so it can be quickly
abstracted out of existence. If most of your time is spent in doing heavy lifting with data defined and
manipulated purely internally, then this paradigm works very well for ensuring that your code is executed
quickly and safely.
This is considered another form of functional programming, although it is very different from the logical/
mathematical paradigm. Instead, the homoiconic paradigm draws from the mathematics of computability
theory. (For the mathematically inclined, homoiconic programming is the lambda calculus as a
programming language.) In the case of a homoiconic programming language, the program processs itself,
performing mechanical reductions on the application until there is nothing left except the answer.
This is a very strange concept for people to wrap their head around, but it is easy to see it in action. To
see it in action, start by assuming that I define this transformation:
For All x, Replace sq(x) With x*x.
Note that I am not defining a function or any kind of semantics: this is not a definition of a function. I
am saying that when a particular set of characters is encountered within the program, we should replace
them with a different set of characters. Now let's say that I define another couple of transformations:
For All f x y z, Replace map(f (x y z)) With (f(x) f(y) f(z)).
For All x y z, Replace sum(x y z) With x+y+z.