Domain Specific Languages in CoffeeScript

CoffeeScript Zen

One of the great features of the CoffeeScript language is the great expressiveness that allows easy creation of Domain Specific Languages (DSLs). In this post I'll explore this aspect of CoffeeScript more with a reflection on how DSLs are done in Ruby.

Why bother with DSLs?

If you are a programmer then you have worked with a lot of DSLs, some of these are:

  • regular expressions
  • SQL
  • CSS
  • etc.

DSLs should not be unknown for you, at least not "external DSLs" like those listed above.

Internal DSLs are another form of DSLs where you use a host language to emulate DSLs. These internal DSLs are only found in languages that are very expressive and that don't have very strict rules. Some host languages include Lisp and Ruby.

In Martin Fowler's FAQ on DSLs he states the most common benefit of using DSLs:

DSLs make certain kinds of code easier to comprehend, which makes it much easier to modify, thus improving programmer productivity. This is worthwhile all on its own and is relatively easy to achieve.

So why should you bother with DSLs? Because they can make you more productive :-)

Examples of DSLs in the Ruby language

Ruby programmers are well known for their usage of DSLs. Let's take a look at how different DSLs look like in the Ruby language.

Ruby On Rails has a lot of DSLs spread around and one of these is in ActiveRecord. The ActiveRecord DSL lets you easily express relationships between model classes:

class Post < ActiveRecord::Base
  has_many :comments
  ...
end

class Comment < ActiveRecord::Base
  belongs_to :post
  ...
end

Sinatra is another Ruby web-framework that includes a DSL for writing request handlers, an example:

get '/', :provides => 'html' do
  haml :index
end

Rake is Ruby's version of make. It includes a DSL which looks like this:

task :i_am_a_task do
    puts "Just a silly task"
end

jQuery: JavaScript's most popular DSL

While JavaScript does not promote creation of DSLs they are still possible. The most popular JavaScript library jQuery can be seen as an internal DSL for selection and manipulation of DOM nodes:

$('.mydiv').addClass('flash').draggable().css('color', 'blue')

So DSLs are possible in JavaScript, but creating them isn't that easy due to JavaScript's strict syntax. Luckily we have CoffeeScript that compiles to JavaScript :-)

zappa: Example of a working DSL in CoffeeScript

zappa is a CoffeeScript DSL for writing node.js web-applications. Here is an example of how a zappa application looks like:

get '/:foo': ->
  @foo += '!'
  render 'index'

view index: ->
  h1 'You said:'
  p @foo

layout ->
  html ->
    head -> title "You said: #{@foo}"
    body -> @content

As you see above CoffeeScript allows a lot and with this it's possible to build very powerful DSLs.

Let's now take a look at different stuff we can do in CoffeeScript.

ActiveRecord's DSL in CoffeeScript

If we need to do an ORM for CoffeeScript we could create one that looks similar to Rails ActiveRecord:

class Post extends ActiveRecord
    has_many: 'comments'

class Comment extends ActiveRecord
    belongs_to: 'post'

Sinatra DSL in CoffeeScript

If we need to handle requests we could emulate Sinatra's DSL:

get '/helloWorld/:name', (name) ->
    "Hello #{ name }"

Rake DSL in CoffeeScript

If we are creating a make system we could emulate rake's DSL:

task "kill_hal", ->
    alert "I am sorry Dave, I'm afraid I can't do that"

DSL for doing Ajax requests

On the client side we could have a DSL for doing Ajax requests, it could look similar to this:

ajaxRequest '/Projects/getProject'
    data:
        project_id: 1
    callback: (response) ->
        alert response

Just for the record, the above code will look like this when compiled to JavaScript:

ajaxRequest('/Projects/getProject', {
  data: {
    project_id: 1
  },
  callback: function(response) {
    return alert(response);
  }
});

Conclusion

As you have seen in this post CoffeeScript makes it trivial to create DSLs and you can easily emulate Ruby's most popular DSLs. I can only imagine what people are going to do with all this expressive power.

Further reading

Articles:

I also recommend reading Martin Fowler's book on the subject:

12. Mar 2011 Code · Code improvement · Code rewrite · Design · JavaScript
© Amir Salihefendic