Categories: Software Development

TaskScheduler Domain Specific Language converted to Lisp

Oren Eini has written a DSL that uses the Boo language and does a bit of sub-classing. This was in response to a reply to one of his posts by a blogger named Tim Wilde. The purpose of a domain-specific language is to make it easier to talk about the domain. The DSL written is written for the domain of scheduling tasks. Instead of typing out the following:

myTask = new Task("warn if website not alive", (3 * 60), ... )
myTask.start()

You would type out:

task "warn if website not alive" every 3 minutes starting now ...

It’s more readable for other users and it hides details that are unnecessary when talking about the domain.

Tim came up with a C# variant which had roughly 250 lines of code, 8 classes and 6 interfaces. Over-kill in my opinion. Oren came up with something that makes the DSL look cleaner and it uses the Boo language.

Oren says,

There are several interesting things that are going on in the DSL. For a start, we are using Boo’s ability to drop parenthesizes if needed, which gives us a more “keyword” feeling. Another interesting approach is that when the last parameter of a method is a delegate, we can use just create a block and use that as a way to create the delegate.

The keyword feeling is fantastic. But it can be taken much further. Much much further. Lisp comes with very powerful macros that can be used to write DSLs and DSLs have been written in Lisp since before I was born in 1987. Being able to create a DSL by extending a language is nothing new. This is why I’ve implemented my own version of the above DSL in Lisp

My Implementation

Warning: I’m using the Scheme dialect and the MzScheme implementation. I’m using the MzScheme thread library instead of the official multi-threading extension to Scheme.

My implementation uses Scheme and the syntax-rules pattern language. I didn’t much like it but now I am getting used it and may use it more often than the Common Lisp defmacro method. I have no idea exactly what the differences are since I am Lisp beginner, but I was able to use Scheme to write an implementation of this DSL in less than 30 minutes.

The code consists of 3 functions: 2 are placeholders, the other one converts whatever time is given into the equivalent amount in seconds. So, 1 minute turns into 60 seconds and 3 minutes turns into 180 seconds. This is used with the sleep function in each task’s thread which controls how long to wait until the task is executed again.

The 2 Patterns Detected

The code also includes 1 syntax definition that has 2 similar patterns that it can match. The 1st pattern is triggered when the task is not starting immediately. An example:

(task "warn if website is not alive"
      every 3 seconds
      starting in 5 seconds
      when (not (website-alive? "http://example.org"))
      then (notify "admin@example.org" "server down!"))

The 2nd pattern is triggered when the task is starting immediately. This is triggered when the keyword “starting” is followed by the word “now”. The above example re-written to start immediately.

2 Interesting Things

Two interesting things that you must know about this code: literals and named let. Literals are using in the syntax-rules pattern language and are the 1st argument to the syntax-rules call. Literals allow us to include keywords in the pattern, such as now and when.

The other interesting thing is the used of the named let. This is when the 1st argument of a let call, a literal, is the name of the “function” created. The 2nd argument is the list of parameters which can include default values that the “function” will be called with. A named let is typically used to add a recursive loop in the middle of another function.

Conclusion

The download is available here. The code for this domain specific language is very short: 59 lines including comments. It uses no classes and no interfaces. Some ideas for improvements include hooking into a task/thread list so that tasks/threads can be killed or retrieved later on.

Lisp can be used as well and can be more concise than other languages. Domain specific languages are not a new idea and I am happy that software developers are finding great uses for them.

Categories: Software Development

Automating Simple Tasks with Scheme (Competing with Perl, Python and Ruby)

Racket/PLT Scheme Logo

reddit user by the name of alanshutko stated what was necessary to make Scheme, Common Lisp, Haskell, and other non-mainstream languages more appealing to the average programmer.

Compare that with the types of simple programs we see in Perl and Python. “I have a bunch of files, and I want to rename them all according to some pattern.” Common problem, easy solution. “I’ve got a log file full of email addresses, I need to strip them out from the log entries, remove duplicates, and add them to a database.” Again, fairly simple, fairly small, really useful. When Haskell can compete on those types of problems, it’ll be easier to induce people to learn it. (Same with CL, my fav language….)

So here is a Scheme program that does this. It is written to use MzScheme because that’s the only Scheme I have installed in Windows at the moment. Thus, it takes advantage of PLaneT and the other libraries that come with MzScheme.

Hopefully this can convince others that Scheme is a good language for common tasks.
Continue reading “Automating Simple Tasks with Scheme (Competing with Perl, Python and Ruby)”