Info on Smalltalk DSLs or Metaprogramming...

Rich Warren rwmlist at gmail.com
Tue Sep 5 06:46:46 UTC 2006


On Sep 4, 2006, at 4:28 PM, Ramon Leon wrote:

>> As an example, Body can take a variable number of Tag objects.  
>> Java  methods can be defined to accept variable numbers of  
>> parameters, so  this isn't a problem. Tag objects can also be  
>> nested inside other  tags (allowing us to express complete html  
>> hierarchies).  Alternatively, all tags (including body) could  
>> accept any objects-- and internally it calls toString() on the  
>> object. This would let you  pass in a mixture of Tag objects and  
>> literal strings.
>
> True, that would seem to work, but only with the addition saying  
> all setters return "this", so properties of those objects can be  
> set in every possible combination, inline, equivalent to  
> Smalltalk's ; operator.  I've done this in the past, it's ugly, and  
> non idiomatic, and confuses other programmers.  It works  
> surprisingly well, once accustomed to it, but feels like you're  
> working very much against the language.  I embedded SQL into csharp  
> using this technique, mostly for the experience of doing so.t as  
> similar to the API vs framework thing, people tend to like one or  
> the other.

Um, it doesn't need to be that difficult. Java basically treats  
variable length arguments as a collection. You could simply iterate  
over the arguments and add each one (in order) to the tag object.

The original example I gave didn't use any setters--not in the  
conventional sense. For example, body() could simply call toString()  
on anything passed in, concatenating the string from multiple  
arguments. It could then append "<body>" to the front and "</body>"  
to the end. Then it would append the whole string to the current  
document.

Alternatively, each tag could keep its contents as a list of subtags  
and raw string, and everything only get converted to strings (with  
the relevant tags added) at the end.

It would still be uglier than Smalltalk, but it could be a very  
simple solution. Of course, I'd still prefer to do this in either  
Smalltalk, Ruby or Lisp.

>
>> On the other hand, there is a sharp line between interpreted DSLs  
>> and  regular programming. That's one of the reasons I prefer to  
>> use the  term DSL strictly for interpreted DSLs. The term (when  
>> used that way)  has a clear meaning.
>> -Rich-
>
> I fail to see that line, whether code is interpreted or not, imho  
> is orthogonal to the issue of whether or not that code is a DSL.  I  
> find your linking of these concepts, odd, maybe it's me, but they  
> simply aren't related.
>
>

OK, clearly you think the issue of interpreted/non-interpreted is  
orthogonal to the issue of
DSL/non-DSL. I don't think we're going to agree on this, so let's set  
it aside for now. For the following discussion, assume everything is  
a DSL unless explicitly stated otherwise.

In other words, let's discuss the difference between bottom-up  
embedded DSLs and interpreted embedded DSLs.

For me all Bottom-up DSL and regular, non-DSL code  lie on a  
continuum. You can clearly point to either end and say "This is a  
DLS" or "This isn't", but most code lies somewhere in the middle.  
And, the middle gets muddy.

There's a quote I've seen many times (with slightly different  
wording). "Any sufficiently complex project becomes a DSL".  This is  
exactly the type of blurring I'm referring to, and it results in a  
general loss of meaning. If everything becomes a DSL, then the term  
DSL has no meaning.

On the other hand, interpreted DSL and non-interpreted code is not a  
continuum. There is a clear line between the two cases. Something is  
either designed to interpret external strings, or it isn't. There's  
no ambiguity.

Secondly, interpreted DSLs require different techniques than bottom- 
up DSLs. As far as I know, C, C++ and Java cannot natively evaluate  
arbitrary strings the way Ruby and Smalltalk can. In those languages,  
you cannot even write code to interpret external strings without  
building a parser of some sort (thus creating an external DSL). Even  
in Smalltalk and Ruby, evaluating strings requires (at minimum) an  
additional method call. More importantly, you have to decide what  
context you are evaluating the string in.

There are also other decisions that need to be made when building an  
interpreting DS that don't have to be made (or cannot be made) when  
simply building a bottom-up DSL. For example, how do you handle EOL  
symbols? Most Ruby DSLs interpret a line at a time, treating each  
line as a separate command. On the other hand, you could interpret  
the whole text as a chunk and treat EOLs just like any other white  
space.

As you can see, even if you're just repurposing the host language,  
building an interpreting DSL  requires an additional layer of tricks,  
tips and techniques that are not required for bottom-up DSLs.

Finally, there's the underlying reason behind why you're using the  
technique. Bottom-up DSLs are simply a tool for developers.  
Interpreting DSLS can also simplify the development task for  
developers; however, they also give end-users tools to change the  
application's behavior after it has been deployed. So, interpreted  
DSLs can solve a much broader range of problems than bottom-up DSLs.

All of this (unambiguous meaning, clearly different set of  
techniques, and broader range of intentions) are reasons why I prefer  
to limit the term DSL to interpreted DSLs. To my mind, there seems to  
be obvious ambiguity between what is a bottom-up DSL and what isn't  
(as exemplified by the "every significantly complex..." quote).  
Bottom-up DSLs don't require any specialized techniques--you're  
simply creating useful methods, classes and operators. And Bottom-up  
DSLS are simply another type of source code--they don't add any  
additional value outside development (here I'm including maintenance  
and testing--basically everything that's done in-house).

Bottom line is, my definition would make DSLs more obviously  
different from other, more mundane programming techniques.

-Rich-




More information about the Squeak-dev mailing list