HTML + Javascript: Benefits of Turing-Incompleteness
What is the most popular language today? HTML. Spreadsheets are another very popular style of programming. SQL is enduringly popular, in spite of the cognoscenti writing off relational databases as “legacy” - something I vehemently disagree with, by the way.
What is in common across these programming systems? They are each optimized for what they do, and more importantly, they don’t attempt to do everything. In programming language terms, they are Turing-incomplete i.e there are many kinds of programs you cannot write in those languages. Languages like C or Java or Lisp or Ruby are general purpose “universal” languages, while HTML (without Javascript) is limited to the purpose of sending a document for display on a browser. SQL (without the vendor proprietary extension languages like PL-SQL) serves to query relational databases. Spreadsheets (without macros) allow you to do rapidly build a variety of number crunching applications.
When we need the full power, we combine HTML with a Turing complete language Javascript. Technically HTML + Javascript is equivalent in computing power to Javascript alone, but that is no reason to discard HTML. Same way we embed SQL in a Turing complete language like C or Java or equivalently, use something like PL-SQL or T-SQL to build applications.
What the success of these ideas shows is the power of combining a Turing incomplete “domain specific” language like HTML or SQL, and embedding or augmenting it with a universal language. The resulting solution turns out to be far simpler (for the humans) than writing everything in a universal language. It is the old divide-and-conquer strategy at work.
HTML and SQL are known as declarative languages - we just tell the computer what we want, without specifying how it gets done. By adopting the HTML + Javascript or SQL + Java solution, in effect we extract a declarative core of the application and separate it from the rest of the program. Declarative programs are easier for the human to write as well as understand - it is always easy to declare “I want a cup of coffee with milk and sugar” rather than specify the steps involved with “Grind the coffee beans, put it in the filter, ….” One problem with specifying all the steps is that the coffee-maker now has no flexibility - for example, it cannot pre-grind the beans in anticipation.
Keeping it declarative is not only simpler for the programmer, but it also allows the run-time system to optimize it. SQL databases optimize queries, and browsers cache HTML pages.
A good part of what is known as “functional style” is really about developing such declarative sub-languages. Lisp macros enable that style. Relational queries follow the same declarative style.