Wednesday, January 9, 2019

PL Design process

Designing a programming language without some idea of what it will be used for is a recipe for failure. The first observation is that programming languages tend to end up with particular patterns or 'styles' of coding and these features get used heavily. For example in Haskell, they have some giant record for keeping track of state, some ADT-tree that gets manipulated, and then various glue code in between. TCL tends towards small programs and throwaway scripts, when bash isn't powerful enough and you need complex loop logic or regular expressions. Agda, Coq, and other proof assistants are so complex to write that they are only written with their accompanying IDE. C++ tends towards giant methods ensconced in a few classes, plus a lot of small copy-paste classes for data storage and interface munging. etc. Honestly though my sample size is small so evaluating this is hard.

Another idea was the schlep filter: writing a compiler is tedious and uninteresting. Hence any language gets a small boost once it's implemented, as other people will use it instead of writing their own. We can imagine a conversion funnel: name recognition -> basic syntax -> toy program -> side project -> startup -> active language developer. Designing a simple website for the PL and measuring conversion rates over time (even if/while it's not implemented) might be useful.

The uninteresting part isn't quite true, by my estimates a new PL gets posted to HN around every 3 months or so. Perhaps information/attention is the most valuable commodity; nobody knows what PL's are out there or what's suited to their project. They might know the library or tool they need though, hence that fixes their choice of PL.

PL design seems to be mostly an art, similar to painting or writing. Since notation is a tool of thought a well-designed PL ends up reshaping the view of the programmer; thoughts that are hard to express are avoided while thoughts that are easy are reinforced. We measure the performance of a PL as in the last post, possibility first then speed and correctness.

Hence I think the best start is a programming examples collection, one might almost say a test suite, where we use and/or implement various abstractions and algorithms. In literate programming the documentation comes with code; here we want the code to be the documentation. It's not so much self-documenting as the knowledge, the meaning, comes from experience with other PL's. For example map is a common function in Haskell but in other languages like C one never sees it as writing it is really hard. And once we write down enough algorithms maybe we can combine them together to form a compiler. So examples should focus on a few beginner coder examples but then mostly compiler algorithms. And then as the language progresses the collection will go from being interesting data to executable test suites. Another good idea is Stone Forth, where any abstraction used must also have its implementation expressed. But this might bog things down, hence why everything starts as a sketch rather than an implementation. We want to design a language starting from the things we want to write and not based on what can be implemented easily, rather that it's implementable at all. VPRI demonstrated with their Nile project that programming language design can make some problems very simple. But Nile itself is pretty big so it's not clear that they actually end up with a reduction in complexity.

No comments:

Post a Comment