June 2017, rev. July 2017

What sets programming languages apart is power: the ability to do what another language can't.

Although languages copy each other to catch up on power, there's a feature almost no language copied because almost none of the most powerful languages have it. Their blind spot: they lack the power to become powerless.

Most powerful languages are unable to relinquish their power. This is such a common occurrance that right now it's axiomatic. A language focused on bringing some new power to life almost never adds the option to turn the new power off.

There are many examples of this. C has direct access to memory, but because pointers can't be disabled programs can crash. OCaml is strict about type safety, but safety checks can't be turned off to use dynamic types. Prolog is good with formal logic, but not informal programming. Python lets programs be simple with little syntax, but can't change the language and can't add syntax.

The pattern here is that if there's a single feature that gives each programming language a unique power, in most cases the feature can't be turned off, to the point that the language becomes crippled for writing some kinds of programs. [1] All else being equal, a language than can let go of its power when the user wants to is more powerful than one that can't.

Since powerlessness is a powerful feature, it would help if we could tell which languages have it. Not just for today's programming languages but also for languages of the future.

I propose a way to test if a language can become powerless. The test is to write a calculator, in as few lines of code as possible, that forbids the user to do anything other than use numbers and the arithmetic operators. For example, it should be impossible to crash the language with a bad pointer or harm the computer by deleting files.

The test is kept simple deliberately. (I can imagine harder tests.) It's easy for a language to show it has the power to lock itself down with this test: just lock down the arithmetic operators. Whereas it's harder for a language designed without powerlessness in mind to add this feature all of the sudden. [2]

Here's a sketch of one possible solution in one line of code in Lisp. [3] The calculation (+ 1 2) is given as input to eval, along with a list of operators the language is allowed to use:

(eval '(+ 1 2) (list '+ '- '* '/)) -> 3

But the language should disallow input that could harm the computer:

(eval '(sys "rm -rf /tmp/*") (list '+ '- '* '/)) -> "access denied for sys"


[1]  Powerlessness doesn't equal safety. There's a lot of room between the two. A programming language can become powerless if it can run slow, or simulate random network errors, or drop features, etc. A good definition might be: a language the user can constrain in some way. By user I mean the programmer, not the language designer.

Powerlessness is also missing from almost all languages, not just the most powerful ones. Some kinds of powerlessness are built-in, like memory-safety and type-safety, but you can't pluck these safety checks out if you want to. (Safety can be both power and powerlessness.) Other kinds are missing, like access to primitives through capabilities.

[2]  It's also a helpful test to run when beginning to design a new language, because one of the first features added in a language are arithmetic operators.

[3]  I'm not saying Lisp does this. Common Lisp doesn't, maybe other Lisp dialects do. It may be easier to change Lisp to pass this test than to change another language.