Is Scala the new Ruby? A deeper view

Facundo Viale
6 min readAug 3, 2014

--

I worked with @fapoli for a few years and after a lot of office discussions i’m going to extend his post Is Scala the new Ruby?. I’m going to give an explanation of the nature of some elements that are mentioned in the post.

The paradigm is the key

Ruby and Scala are both object oriented programming languages. But the true power of Scala comes from the functional programing side. Scala tries to be as functional as it is possible, coexisting with the object oriented paradigm.

Null values

Suppose that we have a variable c that could contain both string or nothing. We want to print that variable and if it contains nothing we want to print a default string:

In Ruby:

if c != nil       # or c.nil?
print c
else
print “something else”
end

In Scala:

if(c != null)
println c
else
println “something else”

Ok, it looks the same. But in the Scala world this is not a functional way to do things and to check against null is unusual. The functional way requires to handle the variables that can be null differently. The correct way is to use the Option Type, that is a type that might contain something or nothing.

Pattern matching style:

c match {
case Some(value) => println value
case None => println “something else”
}

OOP style:

println c.getOrElse(“something else”)

This happens because the type of c is not String, but instead is Option[String]. The type Option is a container of another type that helps us handle a value that might or might not be present. Here is a more complex example, from the Scala Doc:

val name: Option[String] = request getParameter "name"
val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase }
println(upper getOrElse "")

Or in one line:

println( request getParameter("name") map { _.trim } filter { _.length != 0 } map { _.toUpperCase } getOrElse "" )

The methods map and filter are part of the Option type and let us work with the contained value whether the value is present or not.

Monads

In Is Scala the new Ruby?, when we read:

array = [0, 1, 2, 3]val array = List(0, 1, 2, 3)

There is a functional reason why Scala doesn’t use this brackets sintax, used in JS, Ruby and Python. This reason is that the Scala compiler doesn’t handle the collection in any special way: For example, it doesn’t use a special sintax to construct a list or a map. Instead of this, Scala uses the functional structure called Monad (I recommend this video to undestand Monads), and the Scala collections are monads. Scala recognizes this type of structure for their behavior, and it is supported by the compiler. It’s also present in other types like: Option type (Yes, it is a monad).

There is a very good video about monads in Scala that you can see to understand this complex but easy structure.

The immutable way

With data

When we read in Is Scala the new Ruby? how to define classes in Ruby and Scala there is an important fact that is not mentioned. In Scala almost everything is immutable. As Wikipedia says:

Immutable objects are often useful because they are inherently thread-safe. Other benefits are that they are simpler to understand and reason about and offer higher security than mutable objects.

For this reason the most common type of class used in Scala is the Case Class, which is, by default, inmutable and is an algebraic data type. Let’s see an example:

case class Person(name: String, age: Int)val richard = Person(“Richard”, 21)
val steve = Person(“Steve”, 18)
println richard.name // print's Richard
richard.name = "John" // This is ilegal and throws a
// compilation error because
// it is immutable
// If we want to change the name we need to create a new instance
val john = richard.copy(name = "John")

Because the case class is an algebraic data type, we can use pattern matching with them:

val has18YearsOld = (richard, steve) match {
case (Person(_, 18), Person(_, 18)) => “Yes”
case _ => “No”
}

By default, collection classes such as List and Map are immutable, so update-methods return a new instance rather than mutating an existing one.

val arrayOne = List(1, 2, 3, 4)
val arrayTwo = arrayOne.map(_ + 1) // This creates a new array
// with the new elements

While this may sound inefficient, the implementation of these classes and their guarantees of immutability mean that the new instance can re-use existing nodes, which, especially in the case of creating copies, is very efficient.

With behavior

In Ruby it’s as simple as using Metaprogramming and changing any class adding new methods or attributes. But with Scala it is imposible to do the same thing. We cannot change the behavior of an already defined class, because even the classes are immutable.

So, how can i enhance an already defined class in Scala? Well, we can wrap a defined class with a new class that adds new behavior. This sounds tricky but Scala gives us some useful tools.

First method: implicit conversion.

Suppose that we have a tuple and we want to convert a String into a Int

// We define a implicit method in any part of the application// Look the “implicit” keyword
implicit def StringToInt( str: String ) = str.toInt
// We import the method StringToInt for make it available
// in the scope
val a = “1”
val b : Int = a // The variable a is implicitly converted to
// a Int throw the method StringToInt

Of course this is not the most useful case, but it is simple and shows that we can define a function that knows how to transform from a type of data to another type of data.

Second method: Implicit class.

Suppose that the case class Person is part of the Scala library, so we cannot touch it. But we want to transform Person into (String, Int) by calling a method toTuple.

// We define a implicit class in any part of the application// Look the “implicit” keyword
implicit class EnhancePerson(p: Person){
def toTuple = (p.name, p.age) // Or Person.unapply(p).get()
}
// We import the class EnhancePerson for make it available
// in the scope
val richard = Person(“Richard”, 21)
val steve = Person(“Steve”, 18)
val map = List(richard.toTuple, steve.toTuple).toMap

First we define an implicit class that takes a parameter of type Person and defines a method that returns a tuple where the first element is the name and the second is the age. Then we define 2 persons, make a list of the tuple of each person and now we have the type List[(String, Int)] which can be converted into Map[String, Int] using the method toMap.
The magic happens when the compiler detects that the method toTuple is not part of Person, it tries to find in the scope an implicit class that takes a Person as a parameter and has the method toTuple. Then the compiler implicitly make’s an instance of EnhancePerson passing the instance of the person as a parameter.

Conclusión

I think it is pointless to compare the syntax and the basic structures of Scala and Ruby. This is because the big difference between both languages is that Scala philosophy has his roots in the functional paradigm. While both languages are object oriented, Ruby developers focus on imperative programming and Scala developers focus on functional programming.

This gap between imperative and functional programming is big in Scala and requires thinking differently about what is being used. And it is a fact that the theory of functional programming is much bigger than the theory of the imperative programing and the object oriented programming.

Because of all this, I think that Scala is not a new Ruby. This doesn’t mean that you can’t build applications as fast and simple as with Ruby, but like any new language you need to get used to it.

--

--