3 ms·
Little languages are good for little programs. Once your program grows up, a little language starts holding it back. Your program needs a language for grown-u
by alexeiz 8y ago
Little languages are good for little programs. Once your program grows up, a little language starts holding it back. Your program needs a language for grown-ups. The truth is all little languages are quite primitive, and this is by design. Little languages are designed for a specific narrow purpose. Beyond that narrow purpose they are much less expressive, clunky and inefficient.
Real life tasks often require more than one little language. You can start with a simple text extraction using Awk, then use Sed for text conversion, and glue it all together with Bash. But very soon it becomes hard to maintain and extend this collection of scripts and easier to replace them with one Perl or Python program, which can do all of the above and more.
So the bottom line is, use little languages then they suit your task, but know their limitations.
- tekknolagi 8y agoWhat would you say makes gluing those languages together hard to maintain? I've found the opposite, where it's difficult to look through the many dark corners of Perl to do something that could have been accomplished instead by a smaller tool.
- throwawayjava 8y agoI've had a lot of luck with little languages that have an escape hatch into the implementation language. My "little languages" always have atomic programs/expressions whose meaning is given by an implementation in the base language. Sometimes, e.g., when my little language has an optimizing compiler or some fancy semantics, the atomic programs/expressions need a tighter interface than "does something". In those cases, I write down the full semantics of the language and figure out what lemmas I need to prove about atomic programs/expressions in order to prove whatever property I want about the overall language. I then enforce those lemmas at runtime using asserts (or, in the case of termination, wrapper code that enforces a timeout). This pretty much only goes wrong when "everything" is factored out into the atomic programs/expressions. I avoid these situations by only using "little languages" when I can do something useful and difficult using the semantics of the little language. Most common examples include: automatic optimization, automatic parallelization, and automatic verification/static analysis. But even when it does go wrong in this way, it's no the end of the world: if everything is implemented in the atomics, then you just refactor the implementations of the atomic programs/expressions into a library, delete the interpreter/compiler, and write some wrapper code.