Another thing about DSLs is that you have to nail both the D and the L in order to get it right, so they are hard to make. Language design is not at all like program design.
Classical DSLs are harder because of the D. You have to nail the domain/language fit or it's more trouble than it's worth. Even then you don't necessarily win enough to justify the cost: a specialized language needs to be significantly better than "just coding your domain model in your general-purpose language", which is a high bar. There isn't only the cognitive cost of learning a specialized language, there's the interoperability hit (can a general program call the DSL and vice versa), lack of tool support and so on. It doesn't make sense for most domains, especially business domains that don't lend themselves to technical notation.
The thing that bottom-up programming has taught me, not that I'm in any way sophisticated at it, is that good language constructs need to be an order of magnitude more lightweight than good application constructs. Application constructs are what you pack in your car for a road trip, language constructs are what you put in your backpack for a hike. Or another metaphor: application constructs are factory equipment, language constructs are hand tools - if you have to think about how to use it, it sucks. I find it's hard mentally to go back and forth between these two design levels. I'm spending a few days at the language level right now so these things are on my mind.
This is exactly why I've grown wary of DSLs. They have their place, but in a really expressive language like Ruby or Haskell I'd often just prefer to code in the native tongue.