Why Scala – Part 1

Scala is a general-purpose programming language designed to express common programming patterns in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional programming languages, enabling programmers to be more productive. Martin Odersky (the creator of Scala) and his team started development on Scala in 2001 in the programming methods laboratory at EPFL (École Polytechnique Fédérale de Lausanne). Scala made its public debut in January 2004 on the JVM platform and a few months later on the .NET platform.

Even though Scala is fairly new in the language space, it has gained the support of the programming community, which is growing every day. Scala is a rich language in terms of features available to programmers, so without wasting time let’s dive into some of them.

Scala as an object-oriented language

The popularity of programming languages such as Java, C#, and Ruby has made object-oriented programming (OOP) widely acceptable to the majority of programmers. OOP, as its name implies, is a programming paradigm that uses objects. Think of objects as data structures that consist of fields and methods. Object orientation helps to provide structure to your application using classes and objects. It also facilitates composition so you can create large applications from smaller building blocks. There are many OOP languages in the wild, but only a few are fit to be defined as pure object-oriented languages.

What makes a language purely object-oriented? Although the exact definition of the term depends on whom you ask, most will agree a pure object-oriented language should have the following characteristics:

Encapsulation/information hiding.
Inheritance.
Polymorphism/dynamic binding.
All predefined types are objects.
All operations are performed by sending messages to objects.
All user-defined types are objects.
Scala supports all these qualities and uses a pure object-oriented model similar to that of Smalltalk(a pure object-oriented language created by Alan Kay around 1980), where every value is an object, and every operation is a message send. Here’s a simple expression:

1+2

In Scala this expression is interpreted as 1.+(2) by the Scala compiler. That means you’re invoking a + operation on an integer object (in this case, 1) by passing 2 as a parameter. Scala treats operator names like ordinary identifiers. An identifier in Scala is either a sequence of letters and digits starting with a letter or a sequence of operator characters. In addition to +, it’s possible to define methods like <=, -, or *. Along with the pure object-oriented features, Scala has made some innovations on OOP space: Modular mixin composition— This feature of Scala has traits in common with both Java interfaces and abstract classes. You can define contracts using one or more traits and provide implementations for some or all of the methods.
Self-type— A mixin doesn’t depend on any methods or fields of the class that it’s mixed into, but sometimes it’s useful to use fields or methods of the class it’s mixed into, and this feature of Scala is called self-type.
Type abstraction— There are two principle forms of abstraction in programming languages: parameterization and abstract members. Scala supports both forms of abstraction uniformly for types and values.

Scala as a functional language

Before I describe Scala as a functional language, I’ll define functional programming in case you’re not familiar with it. Functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data.

Mutable vs. immutable data
An object is called mutable when you can alter the contents of the object if you have a reference to it. In the case of an immutable object, the contents of the object can’t be altered if you have a reference to it.

It’s easy to create a mutable object; all you have to do is provide access to the mutable state of the object. The disadvantage of mutable objects is keeping track of the changes. In a multithreaded environment you need lock/synchronization techniques to avoid concurrent access. For immutable objects, you don’t have to worry about these situations.

Functional programming takes more of a mathematical view of the world, where programs are composed of functions that take certain input and produce values and possibly other functions. The building blocks of functional programming are neither objects nor procedures (C programming style) but functions. The simple definition of functional programming is programming with functions.

It’s important to understand what is meant by function here. A function relates every value of the domain (the input) to exactly one value of the codomain (the output). Figure below depicts a function that maps values of type X to exactly one value of Y.

getfile (1)

Another aspect of functional programming is that it doesn’t have side effects or mutability. The benefits of not having mutability and side effects in functional programs are that the programs are much easier to understand (it has no side effects), reason about, and test because the activity of the function is completely local and it has no external effects. Another huge benefit of functional programming is ease of concurrent programming. Concurrency becomes a nonissue because there’s no change (immutability) to coordinate between processes or threads.

How do mathematical functions relate to functions in programming?
In mathematics, a function is a relation between a given set of elements called the domain (in programming we call this input) and a set of elements called the codomain (in programming we call this output). The function associates each element in the domain with exactly one element in the codomain. For example, f(x) = y could be interpreted as

x has a relationship f with y or x maps to y via f

If you write your functions keeping in mind the definition of the mathematical function, then for a given input your function should always return the same output.

Let’s see this in a programming context. Say you have the following function that takes two input parameters and produces the sum of them:

def addFunction(a: Int, b: Int) = a + b

For a given input set (2, 3) this function always returns 5, but the following function currentTime doesn’t fit the definition:

def currentTime(timezone: TimeZone) =
Calendar.getInstance(timezone).getTime

For the given timezone GMT, it returns different results based on the time of day.

One other interesting property of a mathematical function is referential transparency, which means that an expression can be replaced with its result. In the case of addFunction, we could replace all the calls made to it with the output value, and the behavior of the program wouldn’t change.

Now let’s talk about functional programming languages. Functional programming languages that support this style of programming provide at least some of the following features:

Higher-order functions
Lexical closures
Pattern matching
Single assignment
Lazy evaluation
Type inference
Tail call optimization
List comprehensions
Mondadic effects

Side effects
A function or expression is said to have a side effect if, in addition to producing a value, it modifies some state or has an observable interaction with calling functions or the outside world. A function might modify a global or a static variable, modify one of its arguments, raise an exception, write data to a display or file, read data, or call other functions having side effects. In the presence of side effects, a program’s behavior depends on its history of execution.

Some of these features are probably unfamiliar if you haven’t done functional programming before.

Is Scala a pure functional language?
Scala, put simply, is not a pure functional language. In a pure functional language modifications are excluded, and variables are used in a mathematical sense, with identifiers referring to immutable and persistent values. An example of a pure functional language is Haskell.

Scala supports both types of variables: single-assignment variables (also called values) that don’t change their value throughout their lifetime and variables that point to a mutable state or could be reassigned to other objects. Even though you should use immutable objects whenever possible, Scala as a language doesn’t provide any restrictions. The restriction is purely conventional. A good rule of thumb is to always default to val and use variables when it’s absolutely necessary.

To me, the fundamental property of a functional language is treating functions as values, and Scala does that well.

Scala supports most of them, but to keep it simple Scala is a functional language in the sense that functions are first-class values. That means that in Scala, every function is a value (like some integer value 1 or some string value “foo”), and like any values, you can pass them as parameters and return them from other functions. In Scala you can assign a function (x: Int) => x + 1 to a val inc and use that to invoke that function:

val inc = (x : Int) => x + 1
inc(1)

Here val represents a single assignment variable (like Java final variables) with a value that can’t be changed after the assignment. The output of the function call is 2.

In the following example you’ll see how to pass functions as parameters to another function and get the result:

List(1, 2, 3).map((x: Int) => x + 1)

In this case you’re passing an increment function to another function called map, and the output produced by the invocation of the map function will be List(2, 3, 4). Based on the output you can see that map is invoking the given function for each element in the list.

Scala as a multi-paradigm language

Scala is a multi-paradigm language because it supports both functional and OOP programming. Scala is the first to unify functional programming and OOP in a statically typed language for the JVM. The obvious question is why we need more than one style of programming.

The goal of multi-paradigm computing is to provide a number of problem-solving styles so a programmer can select the solution that best matches the characteristics of the problem to be solved. This provides a framework where you can work in a variety of styles and mix the constructs from different ones. Functional programming makes it easy to build interesting things from simple parts (functions), and OOP makes it easy to adopt and extend complex systems using inheritance, classes, and so on.

According to researcher Timothy Budd, “Research results from the psychology of programming indicate that expertise in programming is far more strongly related to the number of different programming styles understood by an individual than it is the number of years of experience in programming.”

5 Timothy A. Budd’s personal web page, http://web.engr.oregonstate.edu/~budd/.

How can Scala combine these two different and almost opposite paradigms into one programming language? In the case of OOP, building blocks are objects, and in functional programming building blocks are functions. In Scala, functions are treated as objects.

Functions as Objects
One of the benefits of combining functional programming with object-oriented programming in Scala is treating functions as objects.

Scala, being a functional language, treats functions as values, and you saw one example of assigning a function to a variable. Because all values in Scala are objects, it follows that functions are objects too. Look at the previous example again:

List(1, 2, 3).map((x: Int) => x + 1)

You’re passing the function (x:Int) => x + 1 to the method map as a parameter. When the compiler encounters such a call, it replaces the function parameter with an object, as in the following:

List(1, 2, 3).map(new Function1[Int, Int]{ def apply(x:Int): Int = x + 1})

What’s going on here? Without diving in too deeply for now, when the Scala compiler encounters functions with one parameter, it replaces that call with an instance of class scala.Function1, which implements a method called apply. If you look carefully, you’ll see that the body of the function is translated into the apply method. Likewise, Scala has Function objects for functions with more than one parameter.

As the popularity of multi-paradigm programming increases, the line between functional and object-oriented programming will fade away.

Scala as a scalable and extensible language
Scala stands for scalable language. One of the design goals of Scala is to create a language that will grow and scale with your demand. Scala is suitable for use as a scripting language, as well as for large enterprise applications. Scala’s component abstraction, succinct syntax, and support for both object-oriented and functional programming make the language scalable.

Scala also provides a unique combination of language mechanisms that makes it easy to add new language constructs in the form of libraries. You could use any method as an infix or postfix operator, and closures in Scala can be passed as “pass by name” arguments to other functions (see the next listing). These features make it easier for developers to define new constructs.

Let’s create a new looping construct called loopTill, which is similar to the while loop in the following listing.

Listing 1.1. Creating the loop construct loopTill in Scala
def loopTill(cond: => Boolean)(body: => Unit): Unit = {
if (cond) {
body
loopTill(cond)(body)
}
}
var i = 10

loopTill (i > 0) {
println(i)
i -= 1
}

In this code you’re creating a new loopTill construct by declaring a method called loopTill that takes two parameters. The first parameter is the condition (i > 0) and the second parameter is a closure. As long as the condition evaluates to true, the loopTill function will execute the given closure.

Definition
Closure is a first-class function with free variables that are bound in the lexical environment. In the loopTill example, the free variable is i. Even though it’s defined outside the closure, you could still use it inside. The second parameter in the loopTill example is a closure, and in Scala that’s represented as an object of type scala.Function0.

Extending a language with a library is much easier than extending the language itself because you don’t have to worry about backward compatibility. For example, Scala actor implementation is provided as a library and isn’t part of the Scala language. When the first actor implementation didn’t scale that well, another actor implementation was added to Scala without breaking anything.

Scala runs on the JVM
The best thing about Java is not the language but the JVM. A JVM is a fine piece of machinery, and the Hotspot team has done a good job in improving its performance over the years. Being a JVM language, Scala integrates well with Java and its ecosystem, including tools, libraries, and IDEs. Now most of the IDEs ship with the Scala plug-in so that you can build, run, and test Scala applications inside the IDE. To use Scala you don’t have to get rid of all the investments you’ve made in Java so far. Instead you can reuse them and keep your ROI coming.

Scala compiles to Java byte code, and at the byte-code level you can’t distinguish between Java code and Scala code. They’re the same. You could use the Java class file disassembler javap to disassemble Scala byte code as you could for Java classes.

Another advantage of running Scala on a JVM is that it can harness all the benefits of JVM-like performance and stability out of the box. And being a statically typed language, Scala programs run as fast as Java programs.

But I still haven’t answered the question—why Scala?

In the next article will go better and answer….

References:
Scala in Action
By: Nilanjan Raychaudhuri

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*