Looking at DSLs in .NET
So, of course this gets me excited about the possibilities of seeing such things in IronRuby. After seeing John Lam's presentations at MIX08 and listening to him on various podcasts, I'm excited that they are making such progress and hopefully get it into our hands soon.
But, before we get too deep into things, I just want to take a step back and look quickly at what DSLs are.
Internal and External DSLs?
So, what are DSLs? Well, to put it succinctly, it's a small language that's used for a very narrow task. You can think of these as languages specific to a domain such as medical claims processing, stock trading and so on that only have meaning there. These languages mean very little outside their problem domain and probably wouldn't make sense to anyone outside. I'm very well aware of such things as I've worked in the medical claims processing industry and their terms, calculations and so on are very specific and to solve the problem well, it's best to suit the language best for expressing solutions.
Martin Fowler wrote an article entitled "Language Workbenches: The Killer-App For Domain Specific Languages?" in which he talks about the history of DSLs especially in the Lisp world, but until now really haven't caught on. Martin argues that XML structures such as configuration files, and so on qualify for that status, due to the fact that it is readable by a human and probably a domain expert as well. But Lisp is well know for the Lex/Yacc parsing and expression trees and so on.
Now the real interesting part comes in when we talk about internal versus external DSLs...
External DSLs, quite simply, are those languages that are not in the same language as the main application itself. This means that I could be free to write any free-form code I wish in order to suit my domain specific need. This means that you need to write parsers and then ultimately would need to have a translation boundary between your DSL and your application. This is where I think something like the Dynamic Language Runtime (DLR) could come into play. What I mean by that is that if you write your language parser for the DLR, and I'll get into that shortly. There is a bit of overhead with this of course, plus a good debugger and IDE, but with time and patience things like this can be overcome. Extending such things as #Develop to encompass those pieces is feasible.
Internal DSLs, on the other hand, are the little languages you can create inside your current language of choice. Now languages such as Lisp, Ruby, Scala, Boo, and F# seem a bit more suited for these than the mainstream languages of C++, C# and Java. Of course one of the bigger obstacles is the pesky curly brace which Ruby allows you to discard. F# doesn't have a concept of this either, and instead the indentation scopes the values and functions and so on. Martin has an interesting DSL written in Java that's interesting and could be better applied in different languages.
Thinking About The DLR
As I said before, I'm pretty excited about the DLR and the flexibility it can give me as a software engineer looking for new and better ways to solve my customer's problems. Not only that, but I'm a language geek at heart, what can I say? I've posted several items on building on the DLR in the context of external DSLs as well as writing custom compilers for .NET. Projects such as Irony also appeal to me in that way.
If you want to play around with the DLR, you can get it in one of two places, the IronPython download on CodePlex or on RubyForge with the IronRuby project.
Martin Maly, a member of the DLR team has continued his posts about Building on the DLR. He took some time off to work on some DLR related issues and now is back with some more posts. Let's continue where we left off last time:
- Answering Some Questions
Martin talks about Static and Dynamic Nodes on DLR Trees
- Variations on Trees
Martin talks about DLR trees and LINQ Expression trees
- More questions
Martin talks about implementing a Print method that acts differently per incoming data type
- Extension Methods
Martin talks about adding extension methods to the ToyScript sample
DSLs In Boo?
Oren Eini, aka Ayende, has been working on a book about DSLs called "Building Domain Specific Languages in Boo". Recently, he posted about some sample chapters now available online with the source code. I highly recommend that you at least give it a look. You now have access to the Early Access Edition, and of course you can buy it online. It'll be interesting to see Ayende at ALT.NET Open Spaces, Seattle to see if he wants to cover more of this stuff.
If you're not familiar with Boo, it's one of Ayende's preferred languages. Such tools as Binsor (The DSL for Windsor) were written in Boo. If you're not familiar with the language, it has very similar syntax to Python and formats very nicely. This easily fits Martin Fowler's category as an external DSL. #Develop has some support for Boo to make it a first class language in the .NET family. It also ships as part of the Castle Project. Anyways, a quick sample of Binsor makes it look like a nice DSL for type registration in Castle Windsor in Boo Script:
import Rhino.Commons logger = Component("console_logger", ILogger, ConsoleLogger) |
Check out the first chapter of Ayende's book which is available free online and explore it yourself for DSLs.
DSLs in F#?
Another part that had me intrigued was the possibilities of not only Boo to do this, but F# as well. Robert Pickering covers this in his book, Foundations of F#. If you pay attention to Chapter 11, he covers DSLs in F# and gives a few examples of how you can do so. To me, it's pretty powerful because you have a lot of the built-in features of a functional programming language such as lists, pattern matching and so on. Such examples as given are such things as the arguments parser in F# that is described in the Arg class in Microsoft.FSharp.Compatibility.OCaml namespace. This allows you to parse well known data structures as first class citizens. Martin Fowler also gave such an example from the article I quoted from above. F# lends itself quite well to DSLs in regard to support for lambda expressions.
Don Syme also covers these topics in his book Expert F# in Chapter 9. This covers more language oriented programming techniques, but you can scan some information about building DSLs in F#. Some interesting parts of this come down to Active Patterns which I covered partially yesterday. In the coming weeks, I hope to post some of my forays into this, taking some samples from the Ruby community and applying some of the same functionality in F#.
Conclusion
There is still much yet to be covered in this topic of DSLs in .NET languages. We can go on and on with regards to internal and external DSLs and argue about which language is suited for each. But in the coming weeks, I hope to take some samples and show how they can apply cleanly in F#, and probably run into some language problems where it might not be the best fit. But, that's the fun part about it.