Domain Specific Languages

Today was a good day at work. I wrote a few classes that allow you to access not only a bunch of switches and multiplexers on a PXI system, but lots of GPIB and LAN measurement devices too.

What is so cool about that, you ask?

Well, you can access all these devices by entering a few commands in a Scheme REPL. Just start a small program called “playground” (I’m not very good with names), load the file “devices.scm” and run it. Voilà, you’ve just got full access to the 19″ tower humming next to you. Want to close a switch?

(close-relay s13)

and you’ll hear a soft click from the tower. So there’s some complex gizmo connected to some of the relays. I want it to do something triggered by a carefully timed series of pulses. No problem:

(define (raise-adapter)
  (close-relay s13)
  (sleep 200)
  (open-relay s13)
  (sleep 50)
  (close-relay s14))

As soon as you’ve got the basics up and running, you can add more complex commands. And all the time you’re playing around with the system, designing your own little language for accessing the hardware as you go.

It gets better. A macro later, I can say something like this:

(with-relay s23
  (measure-voltage-dc left-multimeter :voltage-range 15))

and the system closes a relay, performs five measurements with a 50 ms break in between, opens the relay again, and returns the arithmetic mean of the measured values.

Sure, you can do that in any programming language worth a dime. But with Scheme, you don’t have to compile the source all the time. The PC connected to the tower doesn’t run Visual Studio. No need to switch PCs all the time, transferring files via network. Just start a program and experiment. Big productivity win.

But Python and the like have REPLs too! Why do I keep raving about Scheme?

For one, Scheme is incredibly simple. Even if you want to create a full standards-compliant Scheme environment, you’re in for about a month of fun as long as you keep working on it without interruptions. But a simplified variant, without continuations, and the numeric tower stripped down to ints and doubles, can be done in a good 1000 lines of C#. You’re up and running in no time. Want to switch technologies? Just write a Scheme interpreter on top of your new platform, and you’re done. At the moment, I’m using C# at work. All our assembly group tests are written in my little Scheme subset. If one day we decide to go for Linux and, say, Java, I’ll have the runtime ported in no time. All our tests will be running without any modification at all. Hell, I’ve even written some of the device drivers in Scheme.

Secondly, by writing your own interpreter, you know and understand all the code. No searching around in manuals, no surprises when the documentation doesn’t match the source, just your code, the way you know and understand it. You get to keep it simple. And by writing your own thing, instead of relying on a packaged system, you can customize everything. Add a few custom commands? No problem. You are independent. No license hassles, no incompatibilities, nothing. That’s how I like it.

And the most important thing: Scheme allows you to rapidly create your own Domain Specific Language (DSL). You need a special control structure? Write a macro and you’re done. Enough of these macros and a few basic procedures thrown in, and you’ve created your own programming language on top of Scheme, specifically crafted for the problem at hand. If I’m converting a test specification for some assembly group into source code, I don’t care about class structure or threading. I want a simple language that allows me to solve the problem, and nothing else. The more your language is tailored to your current domain, the simpler it will be. Best case you can just write the spec itself in your new language and turn it into a piece of source code to run without modifications. Then, instead of writing 5000 lines of C#, you end up writing 107 lines of Scheme-plus-custom-macros, just like I did today.

There is one caveat, though: Other programmers will have to learn your specific language before they can modify your code. Keep that in mind when documenting the system. But as for my experiences so far — never stop learning — the benefits of using a DSL outweigh that by far. You know you’ve created the right language when someone who isn’t a programmer, but a domain expert, looks at your source and understands it in a instant.

Sure, you can write interpreters for DSLs in any programming language. You can embed, say, Lua or Tcl pretty easily. But show me one single language that is simple to implement, simple to understand, simple to use, AND that allows you to create your own DSL on top of it as simply as Scheme does.

Did I mention I love this little language?


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s