Turing Completeness – Measuring Computational Power Beyond Turing Completeness

turing-completeness

I originally tried asking this on StackOverflow, but it was too subjective :-(. I am interested in methods of defining the power of programming languages. Turing completeness is one, but it is almost universally satisfied. What would be nice is to define a measure of power that discriminates among programming languages that are actually in used. For example, can anyone propose a non-subjective method that would discriminate between assembly and Java?

Turing completeness means that a language is maximally powerful in what it can output (which pretty much means it can do anything non-time based in the real world). So if we want to define a stronger measure of power, we need to take another approach. Shortness was suggested in the original question, but this is not easy to define at all. Does anyone have any other suggestions?

Best Answer

The notion you are looking for is called expressiveness and Matthias Felleisen has a mathematically rigorous definition:

"On the Expressive Power of Programming Languages"

www.ccs.neu.edu/scheme/pubs/scp91-felleisen.ps.gz (Postscript version)

The intuition behind the idea is that if you have two equivalent programs in two different languages-- say, program A in language X and program B in language Y-- and if you make a local change to A that requires a global change to B, then X is more expressive than Y.

One example Felleisen provides is assignment: In the Scheme programming languages you can remove the assignment operator and still have a Turing complete language. However, in such a restricted language, adding in a feature that would be localized if assignment was allowed would require a global change to the program without assignment.

My discussion has simplified some details, and you should read the paper itself for the full account.

To answer your other question: You can say that Java is more expressive than assembly because you can add a new class to your Java program, and then gain the benefits of polymorphism by having other parts of your program call its methods without global modification. Exception handling is another example where Java is more expressive than assembly: You simply need to write a single throw statement to transfer control up the stack. On a more elementary level, you can also add a new case statement near the beginning of a switch and you won't have to worry about recalculating any jump offsets by hand.