Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Introduction to Functional Programming in Scala

Learn more about Scala, a programming language that supports both object-oriented and functional paradigms.


advertisement

Scala is a multi-paradigm programming language in the sense that it supports both object-oriented and functional paradigms. It runs on the JVM and can be installed using the instructions found here: http://scala-lang.org/download/install.html.

Let's explore some of its functional features.

Hello, world!

Who am I not to respect the classic "Hello, world!" program presented when introducing a programming language? So with my utmost respect for Brian Kernighan who created this tradition here's the "Hello, world!" in Scala:



Listing 1: Hello, world!

object HelloWorld {
 def main(args: Array[String]): Unit = {
  println("Hello, world!")
 }
}

The structure of this program consists of a singleton object, HelloWorld, which contains only one method called main. It takes the command line arguments and call the predefined method println passing in the "Hello, world!" string.

From this simple program, you may have already noticed that types in Scala follow the variable name (or parameter name in case of function). Indeed the args parameter is of type Array[String] and the main function returns a value of type Unit. For simplicity's sake think of Unit as the typical void of other languages even if it's not exactly the same.

Immutability

In Functional Programming you tend not to have classes whose state can be changed — the so-called mutable classes. Rather, your model is represented by immutable classes. Scala offers a nice syntax to create them that falls under the name of case classes. Here is a simple example:

Listing 2. Case classes

case class Person(firstname: String, lastname: String, age: Int)

// create instances of the Person class
val bob: Person = Person("Bob", "Smith", 39)
val alice = Person("Alice", "Brown", 31)

// access fields
val aliceAge = alice.age

If you come from a Java background, you'll notice much less boilerplate code. Note also the use of the val keyword. In Scala it is used to create immutable variables, such that once you assign a value to a val reference you can no longer change it. For example something like the following is disallowed:

val a = 42
a = 3 // error: reassignment to val

There's another peculiarity to consider in Listing 2. I didn't forget to declare the type of the alice variable, I left it out on purpose to demonstrate another nice feature of Scala: type inference. In fact, I could have omitted it for bob as well since Scala's type inferer is smart enough to understand its type as it did for alice.

Case classes provides many other goodies along with pattern matching, another fundamental pillar of functional programming languages.

Pattern Matching

If this is your first encounter with pattern matching, you could consider it as an enhanced switch statement, as an oversimplification. Actually it's much more than that. For example, examine the following code:

Listing 3. Pattern Matching

import Shape._

trait Shape

case class Rectangle(base: Double, height: Double) extends Shape
case class Circle(radius: Double) extends Shape

object Shape {

  def area(shape: Shape): Double = shape match {
    case Rectangle(b, h) => b * h
    case Circle(r) => r * r * Math.PI
  }
}

val rectangle: Shape = Rectangle(4, 5)
val circle: Shape = Circle(4)

val rectangleArea = area(rectangle)
val circleArea = area(circle)

The code in bold shows pattern matching. It matches against the shape object passed as a parameter. If it's of type Rectangle it extracts its base and height, whereas if it's a Circle it extracts its radius. In both cases it computes the area of the shape. The extraction part is called deconstruction.

Note also the trait keyword. It's used to define "interfaces" in Scala. I used quotes for the word since they are actually different from, say, Java interfaces but for now this similarity will do.

The import Shape._ part lets you use Shape's area function without fully referencing it as Shape.area.

One more thing. You may have noticed that the name Shape is used both for the trait and object definition. In Scala that's possible and frequently used. In that case the object is called a companion object of the trait and, practically, it has some implications I won't cover here for the sake of brevity.

Pattern matching sounds good, but could a functional language be defined as such if it didn't provide functions as first-class citizens? No, of course it couldn't!

Functions as First Class Citizens

In FP you tend to write pure functions, functions that, given the same input, always return the same output, without producing any side effect. They are functions in the mathematical sense of the term.

A function in a language is first-class if it can be used like any other type, such as Int, String, Double, and so on. This means that it can be assigned to a variable, passed as a parameter to another function or returned by a function. Consider the following code snippet:

val double: Int => Int = x => x * 2

val increment: Int => Int = x => x + 1

def applyFunc(x: Int, f: Int => Int): Int = f(x)

In this case, double is a function from Int to Int. It takes an integer and doubles it. Notice the type definition: Int => Int. The function body — what follows the equals sign — means: "take the integer x provided by the client code and return its value multiplied by 2". Similarly the increment function takes an integer and adds 1 to it.

The applyFunc function takes an integer and a function that takes an integer and returns an integer. The return type of applyFunc is still an integer. This function just applies the function f, passed as a parameter, to the value x, also passed as a parameter. So if you want to apply the double function to your integer you can use this function as follows:

applyFunc(21, double) // the result will be 42

Now you need to apply the increment function instead. Easy:

applyFunc(21, increment) // the result will be 22

In the FP world functions such as applyFunc are called higher-order functions (HOFs). A HOF is a function that takes another function as a parameter and/or returns a function as its result.

Conclusions

Of course the space instantiated for an article is not enough to cover functional programming in all its entirety or all the features of a language about which you could easily write a 1000 page book. This article didn't even scratch the surface of Scala but, hopefully, tickled your brain a little bit.

Big companies such as Twitter, LinkedIn, Netflix, and many others, are already using Scala successfully in production. Now might be a good time to jump on board before you get left out of the boat.

Final Note: In case you're worrying about your beloved Java library, no problem, you can use any Java API from Scala seamlessly.



   
Alessandro Lacava is a software designer and developer. At the moment, he is mainly interested in functional programming and languages such as Scala, Haskell and the like. He also has fun playing with Domain-Specific Languages (DSLs).
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date