Scala vs Ruby - Creating a while loop DSL

1 minute read

I’m learning Scala. It’s a powerful language with lots of features. One such thing is called the by-name parameters

In most languages, a while loop will look like this:

while (condition) {
  # statements
  ...
}

Ruby implementation of this would look like this:

# Define the method first
def my_while(cond, &block)
  if cond.call
    yield
    my_while(cond, &block)
  end
end

i = 0
cond = -> { i < 10 }

# and then call it
my_while(cond) do
  puts "i: #{i}"
  i += 1
end

This is the best I could do. The condition has to be declared explicitly as an anonymous function (proc/lambda/block whatever!). It doesn’t quite give you the native while look.

But in Scala we could have a function that looks exactly like the native while. Here’s how:

// Define the method first
def my_while(cond: => Boolean)(body: => Unit): Unit =
  if (cond) {
    body
    my_while(cond)(body)
  }

var j = 0

// and then call it.
my_while(j < 10) {
  println(s"j: ${j}")
  j += 1
}

This is because the first argument to the function - cond - is declared as a by-name parameter. This means the compiler will treat it as an anonymous function. And then whenever the cond is referred in the function definition, this anonymous function will be executed and it’s return value be put in its place.

The tradeoff here is, when someone looks at the calling code, especially the condition j < 10, they might think of it as a simple boolean expression and think that it’s evaluated immediately on first call. It might trip them. They’ll have to see the method definition to really know that it’s a by-name parameter instead of a normal boolean one.

With Ruby, the tradeoff is that the calling code doesn’t look like the native dsl. But the great part is that anyone coming across the calling code anywhere will know exactly what the method is going to do with the anon function that was passed.

I prefer the Ruby way, but was really impressed that Scala could do it exactly as per the DSL.

Tags: ,

Updated: