It's a solidly thorough list, but the upshot should really be "designing a general-purpose language is hard."
Designing a special-purpose language or a DSL is easier, but in my experience a lot of seeming DSLs end up slowly accreting more and more features over time that make them look more like general purpose languages. For example, you start with something simple, but then you realize you need conditionals, then you decide to add loops, then you need some concept of packaging and subroutines, etc. Done in that sort of ad-hoc fashion over time can leave things a mess, and if you knew you'd have to do that much work, you never would have tried to make a DSL in the first place.
The other problem with DSLs is that it provides another set of rules you need to keep in your mind around things like coping, evaluation order, naming conventions, etc. in addition to any other languages you know.
So my personal bias these days is to work within a flexible language if possible and to use metaprogramming where necessary to create a reasonable API; Ruby and Lisp are pretty obvious candidates there.
My company has its own statically-typed JVM scripting language that's gone through some of that evolution, from rules-only configuration language to a full-fledged language with classes, closures, etc. In order to curb the proliferation of mini-DSLs we had for various parts of the system, we instead opened up the type system of the language and allow for essentially a form of type-safe metaprogramming, which lets us get good, clean APIs for things that used to be DSLs while maintaining a single set of language rules and allowing for the use of other language features (adding methods that take blocks to the custom types, for example) in combination with the DSL-ish stuff.
Another suggestion: a very useful tool for designing a language is the new OMeta language from VPRI: a language for creating executable grammars - i.e. writing new languages quickly. see http://www.cs.ucla.edu/~awarth/ometa/
My rule of thumb is that if you think the solution is to create a language, you have not thought about the problem enough. Obviously there are exceptions (I know language designers, etc), but you should have a really clear reason why and an appreciation and/or desire for why not to.
Anything sufficiently complex that you code is will quickly approach being a language.
The .NET class library is a language - if you built a a reasonably sized Class Model in Java it would be a language... Thinking about it in terms of language constructs can give a lot of very useful insights.
Designing a special-purpose language or a DSL is easier, but in my experience a lot of seeming DSLs end up slowly accreting more and more features over time that make them look more like general purpose languages. For example, you start with something simple, but then you realize you need conditionals, then you decide to add loops, then you need some concept of packaging and subroutines, etc. Done in that sort of ad-hoc fashion over time can leave things a mess, and if you knew you'd have to do that much work, you never would have tried to make a DSL in the first place.
The other problem with DSLs is that it provides another set of rules you need to keep in your mind around things like coping, evaluation order, naming conventions, etc. in addition to any other languages you know.
So my personal bias these days is to work within a flexible language if possible and to use metaprogramming where necessary to create a reasonable API; Ruby and Lisp are pretty obvious candidates there.
My company has its own statically-typed JVM scripting language that's gone through some of that evolution, from rules-only configuration language to a full-fledged language with classes, closures, etc. In order to curb the proliferation of mini-DSLs we had for various parts of the system, we instead opened up the type system of the language and allow for essentially a form of type-safe metaprogramming, which lets us get good, clean APIs for things that used to be DSLs while maintaining a single set of language rules and allowing for the use of other language features (adding methods that take blocks to the custom types, for example) in combination with the DSL-ish stuff.