| The languages that truly let you do anything you want flexibly invariably lead to incomprehensible ivory towers. It is why managers hate Lisp, it's why Perl is joked as write-once read-never. The issue with the "DSL" is the third letter in the abbreviation: LANGUAGE. A language isn't just a specification of syntax. A language is a collective shared understanding between a sufficiently large number of people. Without that, it is a dead language. Socially in programming, programming languages need to align to real-world concepts, because that is what enables the language to be understood by new adopters. And converging on those shared meanings is hard, because designers and lingo makers can't anticipate all the variations of understanding people will have. Learning a language is hard. So every DSL I've encountered invariably forces me to be the compiler: what is this being translated into language-wise and what does it convert to. That is a big load, so your DSL better provide power and convenience to deserve it. DSLs also run headlong into NIH/creator's advantage. The people/person that make the DSL and implement it will know it FAR better than any adopter will. And documentation is always lacking. So what is blindingly obvious to the core practitioners is very much not so to the noob. You are limited by the average intelligence of the programmer at a cultural level. The lone mad scientist may produce amazing ideas, but all the groundbreaking technology happens because an army of people can be coordinated to implement something. Lisp is basically a DSL factory, and everything is done via DSL. Can Perl7 do that better than Lisp? Is that a good or bad thing? Well, it doesn't matter. Perl5 is what it is. Perl6 was a social failure. I doubt Perl7 will change anything. |
I've yet to see that happen in a Lisp project. On the other hand, inflexible languages like Java lead to abominations like the Spring framework, where tons metaprogramming happens at runtime via reflection.
The thing about compile-time macros (e.g. Lisp macros) is that they can be debugged at compile time. For example, if you see a macro invocation, and you don't know what it does, you can just expand that macro right in your editor, and look at what code was generated.
People are always worried about DSLs, but most projects end up with their own DSLs. They're just often built out of functions, methods, objects, etc.
I think the real issue with understanding a project is learning the concepts, architecture, and abstractions they use. Knowing e.g. Go really well doesn't save you from having to wade through the giant pile of code used to express the program's intent. Abstraction is a way to get that complexity filtered down as close to the problem's inherent complexity as possible. Yes, you'll have to learn the abstractions, but if done reasonably well, that will still be much easier than trying to understand the non-abstracted version.