DSL (Domain Specific Language) is a programming language or specification language dedicated to a particular problem domain, problem representation or a particular solution technique. So with a few Scala Nuggets on our way we are ready to write a DSL? Not quite but in this post we would touch upon a critical feature in Scala which makes writing DSL’s easy.
Let us look at the following code snippet.
[sourcecode language=”scala”]
println (1+2)
println (1 .+(2))
println (1.+(2))
println (1 +(2))
[/sourcecode]
and if I tell you that the output is the following
3
3
3.0
3
How do you interpret that? Well, the first one is easy and that is how we do it in Java also. What about println (1 .+(2)). How on earth can I do that?
In Scala, all operators are methods. So, in our example, + is actually a method which can be called on 1. Hence what we are essentially doing here is that we are calling 1.someMethod(2) and in our case someMethod happens to be +
Aha, and why is there a space between 1 and the period(.) This is because if we do not give the space, the compiler assumes that we are calling the method + on a Double. That is the reason that you see the output of println (1.+(2)) as 3.0
Ok and what the hell is println (1 +(2)). Well, actually it is the same thing as you can see from the output but Scala allows you to omit the period and the parentheses when the method takes only one argument. So we have omitted the period here and in the first line i.e. println (1+2), we have omitted both the period and the parentheses.
Also if a method takes no argument but is defined with empty argument list then we can call the method either by including the parentheses or omitting it. Hence the following
[sourcecode language=”scala”]
def methodWithNoArgs(){
println("No Argument Method")
}
[/sourcecode]
can be accessed with either of the two
methodWithNoArgs
methodWithNoArgs()
However, if the method is defined with no parentheses, something like this
[sourcecode language=”scala”]
def methodWithNoArgsAndNoParenthesesEither{
println("No Argument No Parantheses Method")
}
[/sourcecode]
then only this methodWithNoArgsAndNoParenthesesEither would work and methodWithNoArgsAndNoParenthesesEither() would not.
How does it help with DSL? Lets look at an example. There is a company called Inphina, which has a method call to see whether the Air Conditioning can we switched on or not.
[sourcecode language=”scala”]
object Inphina {
def switchOnACat(n:Int):Boolean={
if (n>35){
return true
} else{
return false
}
}
[/sourcecode]
As you can see that the AC can be switched on when the temperature is > 35. Let us see how we can invoke it now. One way of calling is the routine way which is
[sourcecode language=”scala”]
val x = Inphina.switchOnACat(37);
println(x)
[/sourcecode]
Another way is to make it more reader friendly and more like English sentence
[sourcecode language=”scala”]
println(Inphina switchOnACat 37)
[/sourcecode]
Since the switchOnACat method takes one argument hence we can omit the period and parentheses and get more readability.
What about the following
[sourcecode language=”scala”]
(List(1, 2, 3, 4).filter(isEven)).foreach(println)
def isEven(n: Int) = (n % 2) == 0
[/sourcecode]
Applying the above principles of method, period and parentheses, we get the same results with
List(1, 2, 3, 4) filter isEven foreach println
Cool isn’t it! We will get into advanced DSL on our way by consuming Scala Nuggets one by one!
The last example could be much more elegantly be written:
def switchOnACat(n:Int) = n > 35