Programming Languages and the Mind
Paul Graham made sonorous assertions in his article “Beating the average” claiming the effectiveness of Lisp over traditional programming languages. The killer feature, as I observed, buried deep in layers of hand-waving arguments for Lisp, is the perfect mirroring from Lisp code to Lisp data structures. Few other if any imperative languages retrofitted with functional characteristics ever receives this ability. If you’ve heard of abstract syntax trees, or ASTs, and may have written a parser that transforms a string of source code to ASTs, you’d be surprised to see that a fully-loaded Lisp program is the AST. That has lead to the proliferation of macros, programs operating on programs, thereby enabling vast classes of meta-thinking to manifest itself cleanly in those weird parentheses.
Some pronounces a language functional as long as it has first-order-functions. Others take a step back and believes that functional languages are also marked by constant-time list insertion and removal. I would say that to be functional, a language has to trivially parse itself. If writing a minimal interpreter requires anything above a few hundred lines of code the language is not properly functional. At this point it seems ambiguous to call an imperative language with closures “functional” and apply the very label to more powerful counterparts like Scheme and Lisp. Perhaps the name “meta-language” will fit them better.
The “blub language” thought experiment Dr. Graham gleefully used to illustrate that the average programmers do not appreciate the power of Lisp is somewhat overboard. I do not consider myself a proficient Lisper to any extent, and not even a good functional programmer. I’ve not used Lisp, Scheme, Haskell or anything similar but I understand the potentials of functional and meta programming and is willing to give it a try if time permits (read: in the distant future). The enterprise landscape for functional languages is changing, too: Twitter and Box have embraced Scala and are shipping products fast. The trading company Jane Street is using OCaml for all of its algorithms and is doing quite well. In the meantime however, bigger players such as Google and Microsoft are still hesitant at making the switch probably due to the continued lackadaisical reception of functional languages by the above-average-but-not-too-much-above programmers. The latter company even has a functional language of its own: F#, but not much dogfooding.
The right perspective, as many are beginning to discover, is that programming languages are not ways of telling the computer HOW to do things. Rather, they are mechanisms of expressing WHAT needs to be done. The more efficient it connects the mind to the computer, the faster programmers can get things done. Lets use a similar method of reasoning as Dr. Graham did. Consider the absolutely expressive programming language: MindLang. It is powered by the latest brain-machine interface and seamlessly converts concepts in your mind to instructions in the computer. The minute you realize your product needs a user database, the compiler will instantly generate a schema projected from your intuitive understanding of humans, and will dynamically optimize the fields as you reason more about the subject. Execution is implemented by emulating a crowdsourced repository of minds from the best project managers over the imagined proposal. Surely such a language will take programming to its extreme. Functional languages are far inferior in comparison, but they’re a correct step forward. Our brains make deductions using a process called variable binding, where pieces of information are organically assigned slots in the limited array of mental capacity, but do not update. Traditional imperative languages inexorably pose mental speed-bumps when we’re analyzing their behaviors: in our comfortable mode of reasoning there are no _i’_s nor j’s; there are entities that accumulate connotations and don’t easily change. In order to make arguments about programs we resort to manually extracting monotonic, higher-level concepts: proposition X is true upon entry into loop iteration no matter what i is. Functional languages have by default made data structures immutable, which interoperates better with our mental model. The same arguments apply for the introduction of domain-specific languages. Whatever you think, you can write, and it works.
So programming languages are really the brain-machine medium, and a bad language simply makes you wrap your brain when writing it. The worse it is, the more migraines you can expect. I took a CS course with an unusual proclivity for design patterns and was sick of it. “Visitor pattern”, “Specification by subclass”, oh well. Many are merely poor man’s version of a more general feature in a better language. So Java does single dispatch, okay, don’t worry, just use the visitor pattern and write your implementation in the subclasses. Right, and now you’ve got multiple dispatch in Scala and poof, the kludge goes away. I wouldn’t go into more details with anonymous classes vs. functions etc. Just so this post does not turn into a complaint-box against Java, I’d like to point out that these are inherited (well everybody likes inheritance) all the way from the early prototypes of inheritance theory and object-oriented programming. People talk about high cohesion and low coupling, but nobody makes a greater case with brain-power-per-functionality, a somewhat correlated but different indicator.
There are places where object-oriented programming performs well: when things are actually objects. I wrote a window compositor in graphics user-interface code for ECE391 and it was a joy to unleash the full power of C++ and its object model: window moves, drags and renders, mouse moves, drags (trivially) and renders, a button moves, drags and renders. Let’s arrange them in a tree and render them all! So OOP works, but only where it’s supposed to work. The more extraneous imaginary concepts you invent: user profile manager, abstract content policy factories, IDoSomethingProvider, dump-everything-in-me-singleton, the more distant the code is bound to get from your mind, and overall programmer efficiency decays.
To wrap things up, mobilize your mind when picking a language (really).