Chapter 2. Getting started

This chapter covers

  • Working with the Scala REPL
  • Scala basics
  • For-comprehensions and pattern matching
  • Building a complete REST client in Scala

In chapter 1 you learned what Scala is and how it compares to other programming languages. I described the concepts at a high level, and in the next few chapters you’re going to revisit those concepts and explore them in detail using examples. In this chapter you learn about the basic Scala types, functions, for-comprehensions, pattern matching, and the other usual suspects.

Some of the concepts in this chapter, like pattern matching and for-comprehensions, are functional programming concepts. But because Scala is a multi-paradigm language, I cover them with the rest of the nonfunctional programming concepts. The objective of this chapter is for you to become comfortable with the basics of the Scala language and its environment so you can start writing Scala programs. Early on, I focus on only the Scala interpreter and its REPL environment (you’ll see it in the next section) to keep things simple.

Before going any farther, make sure your Scala installation is working. Throughout the chapter you’re going to work with various Scala examples, and it would be better if you tried them in the Scala interpreter at the same time. Now let’s have some fun with the Scala interpreter.

2.1. REPL with Scala interpreter

The easiest way to get started with Scala is by using the Scala interpreter, an interactive shell for writing Scala expressions and programs. To start the Scala interpreter in interactive mode, type scala at the command prompt. If everything goes fine with your installation, you’ll see something like the following:

Welcome to Scala version 2.10.0.final (Java ...).
Type in expressions to have them evaluated.
Type :help for more information.

scala>

This means your Scala installation is successful. I’m running Scala version 2.10.0, and all the code examples should work for this version and above. At the Scala prompt type 42 and press Enter, and you should see something like this:

scala> 42
res0: Int = 42

The first line is what you typed. The Scala interpreter reads the input 42, evaluates it as an integer literal, creates an Int type object representing the number 42, and prints it back to the console. res0 is the name of the variable created by the Scala interpreter (the name of the variable could be different for you because the variable name is generated by the Scala interpreter at runtime) and it holds the value 42. If you type the variable name, in this case res0, at the prompt, you’ll get similar output:

scala> res0
res1: Int = 42

These steps together are called read-evaluate-print loop (REPL). You could loop read-evaluate-print steps repeatedly inside the Scala interpreter. Now you’ll write your first “Hello world” program in Scala:

scala> println("Hello world")
Hello world

You’re evaluating the println function by passing the "Hello world" string as a parameter, and Scala outputs the same string.

Definition

println is a function defined in scala.Console, which in turn uses System.out.println to print messages to the console. Scala Predef (part of the standard library) maps println to Console.println for you so you don’t have to prefix it with Console when using it.

In chapter 1, I mentioned that Scala integrates well with Java but didn’t provide an example. I’ll fix that now:

scala> val myList = new java.util.ArrayList[String]()
myList: java.util.ArrayList[String] = []

In this case you’re creating an instance of java.util.ArrayList that will hold String-type objects. If you don’t remember all the methods that you could possibly invoke on myList, don’t worry because the Scala interpreter will help you with that. Type in myList, followed by a period, and press Tab; the Scala interpreter lists all the methods you can invoke. Not only does it list all the methods associated with a data type, it also autocompletes variable names and class names that are known to the interpreter. I encourage you to spend some time with the Scala interpreter, explore the available options, and keep it handy when working through the examples in this book. Consider REPL as an essential part of learning a new language because it gives quick feedback. Table 2.1 explains the REPL options available to you.

Table 2.1. Important Scala interpreter commands

Command

Description

:help This command prints the help message with all the commands available in the Scala interpreter.
:cp Use this command to add a JAR file to the classpath for the Scala interpreter. For example, :cp tools/junit.jar will try to find a JUnit JAR file relative to your current location and, if found, it will add the JAR file to your classpath so that you can refer to the classes inside the JAR file.
:load or :l Allows you to load Scala files into the interpreter. If you want to investigate existing Scala code, you could load the file into the Scala interpreter, and all the definitions will be accessible to you.
:replay or :r Resets the interpreter and replays all the previous commands.
:quit or :q Exits the interpreter.
:type Displays the type of an expression without evaluating it. For example, :type 1 + 2 will determine the type of the expression to Int without performing the add operation.

2.2. Scala basics

In this section I round out basic Scala information with examples so you can gradually get comfortable with the language. You’ll use the Scala REPL to try out the examples, but you can use any of the development environments mentioned in the previous section that suit you.

In the following sections you’ll explore basic Scala types, including String and the value types Byte, Short, Int, Long, Float, Double, Boolean, and Char. You’ll learn about two types of Scala variables, var and val, how they’re used, and how they’re different. You’ll also learn about the Scala functions, how to define them, and ways you can invoke them. Let’s start with the basic data types in Scala.

2.2.1. Basic types

If you’re a Java programmer, you’ll be glad to know that Scala supports all the basic value types (primitives): Byte, Short, Int, Float, Double, Boolean, and Char. Table 2.2 shows all eight basic value types supported by Scala. In Scala all the basic types are objects, and they’re defined under the scala package.

Table 2.2. Scala basic types

Value type

Description and range

Byte 8-bit signed 2’s complement integer. It has minimum value of –128 and a maximum value of 127 (inclusive).
Short 16-bit signed 2’s complement integer. It has a minimum value of –32,768 and maximum of 32,767 (inclusive).
Int 32-bit signed 2’s complement integer. It has a minimum value of –2,147,483,648 and a maximum value of 2,147,483,647 (inclusive).
Long 64-bit signed 2’s complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive).
Float A single-precision 32-bit IEEE 754 floating point.
Double A double-precision 64-bit IEEE 754 floating point.
Boolean Two possible values: true and false.
Char A single 16-bit Unicode character. It has a minimum value of ‘u0000’ (or 0) and a maximum value of ‘uffff’ (or 65,535 inclusive).

In Scala all the basic types are declared using initial caps. Instead of declaring something as int, in Scala it’s declared as Int. In earlier versions of Scala, programmers could use lowercase and uppercase interchangeably, but from version 2.8 on, if you declare any variable with int, you’ll get a compiler error:

scala> val x:int = 1
<console>:4: error: not found: type
     int
val x:int = 1

The following is fine with the compiler:

scala> val x:Int = 1
x: Int = 1
A small fact about Scala Predef

The Scala compiler implicitly imports java.lang, the scala package, and an object called scala.Predef to every compilation unit or Scala program. In the case of .NET instead of java.lang, it imports the system package. The Predef object defines standard functions and type aliases for Scala programs. Because this object is imported automatically, all members of this object are available to you. Predef is interesting, and you can learn a lot about Scala by looking at the scaladoc or source of the scala.Predef object.

Even though the full qualifying name of Int is scala.Int, you can use only Int because the scala package is automatically imported into every Scala source, so you don’t have to fully qualify the basic types.[1]

1 Documentation for the Scala standard library, www.scala-lang.org/docu/files/api/index.html.

To see all packages that are automatically imported, use the :imports command inside REPL:

scala> :imports
 1) import java.lang._             (153 types, 158 terms)
 2) import scala._                 (798 types, 806 terms)
 3) import scala.Predef._          (16 types, 167 terms, 96 are implicit)

In this case, java.lang, scala, and scala.Predef packages are automatically imported when you start a REPL session.

Integer Literals

Of the basic types defined in table 2.2, Byte, Short, Int, Long, and Char are collectively called integral types. The integer literals can represent decimal, hexadecimal, and octal numbers. They’re determined by the way the literal is defined. If the literal is 0 or any nonzero digits, it’s a decimal number:

scala> val decimal = 11235
decimal: Int = 11235
Definition

A literal is a shorthand way to describe an object. The shorthand expression matches the structure of the project. You could create a string object by using the string literal "one" and also using the new keyword, as in new String("one").

Because integer literals are usually integers, Scala infers the type as integer, but if you want a Long type, you could add the suffix L or l:

scala> val decimal = 11235L
decimal: Long = 11235

Hexadecimal numbers start with 0x, and octal numbers should be prefixed with 0:

scala> val hexa = 0x23
hexa: Int = 35

scala> val octa = 023
hexa: Int = 19

One thing to note while using hexadecimal and octal numbers is that the Scala interpreter always evaluates the result as a decimal number. You can specify the type of variable (sometimes called only value; more on this later) that you want when you think Scala type inference isn’t producing the result you are seeking. If you declare a variable with an integer literal, for example, Scala creates a variable of type integer unless it can’t fit the value within the range of integer values. In that case the Scala compiler throws an error. What do you do if you want a Byte type variable? You declare the type Byte when creating the variable:

scala> val i  = 1
i: Int = 1

scala> val i2: Byte = 1
i2: Byte = 1
Floating-Point Literals

Floating-point literals are composed of digits with a decimal point and an exponent part. But both the decimal point and the exponent part are optional. Floating-point literals are of type Float when they’re suffixed with F or f and are Double otherwise:

scala> val d  = 0.0
d: Double = 0.0

scala> val f = 0.0f
f: Float = 0.0

You can also create a Double variable with an exponent part. To declare a variable with the value of 1 times 10 to the power of 30 (1 times 10^30), it would look like this:

scala>val exponent = 1e30
exponent: Double = 1.0E30
A corner case with floating literals

In floating literals you could define a Double value as 1.0 or as 1, without the trailing zero or digits. In Scala you can invoke a method with a decimal point (.) followed by a method name, because all basic types (primitives) are objects in Scala, and like all other Scala objects they have a toString method. This raises an interesting corner case when invoking methods on floating literals. To invoke a toString method on the 1. floating literal, what should you do? You have to put a space between the dot and the toString method, like this: 1. toString. If you try it as 1.toString without the space, it invokes the toString method defined in the Int object. This is necessary only when the method name starts with a letter. For example, 1.+1 works fine and produces the desired output, 2.0.

Character Literals

A character literal is a single character enclosed in quotes. The character can be a printable Unicode character or an escape sequence:

scala> val capB = '102'
capB: Char = B

scala> val capB = 'B'
capB: Char = B

You can also assign special character literal escape sequences to Char type variables:

scala> val new_line = '
'
new_line: Char =

Because the new_line character is nonprintable, unlike others, the value of the new_line variable doesn’t show up in the Scala interpreter. All the character escapes in Java and .NET are supported. Scala takes programming with Unicode characters to the next level. You can use not only literals but also printable Unicode characters as variable and method names. To create a variable name ans with the value 42 using Unicode characters, you would do something like the following:

scala> val u0061u006eu0073 = 42
ans: Int = 42

Using Unicode characters for naming variables or functions in a program is a way to get yelled at by your peers, but in some contexts it improves the readability of the code.[2] In the following example Unicode characters are used in the variable and method name:

2 “Boolean Algebra Internal DSL in Scala,” Gabriel’s software development blog, June 2, 2009, http://mng.bz/w2V3.

val ? = scala.math.Pi

def ?(x:Double) = scala.math.sqrt(x)

Before trying out these examples, make sure your editor supports Unicode encoding.

String Literals

A string literal is a sequence of characters in double quotes. The characters are either printable Unicode characters or escape sequences. If the string literal contains a double-quote character, it must be escaped with a slash ():

scala> val bookName = "Scala in "Action""
bookName: java.lang.String = Scala in "Action"

The value of the string literal is of type String. Unlike other basic types, String is an instance of java.lang.String. As mentioned earlier, it’s automatically imported for you. Scala also supports a special multiline string literal that’s enclosed in triple quotes ("""). The sequence of characters is arbitrary, except that it may not contain a triple quote, and it doesn’t even necessarily have to be printable:

scala> val multiLine = """This is a
     |                     multi line
     |                     string"""
multiLine: java.lang.String =
This is a
            multi line
            string

The output of the multiLine variable has leading whitespaces, and maybe you don’t want that. There’s an easy fix—invoking a method called stripMargin strips out the margin for you:

scala> val multiLine = """This is a
     | |multi line
     | |string""".stripMargin
multiLine: String =
This is a
multi line
string

This code may seem a little confusing. The first | (vertical bar) or margin is added by the interpreter when you press Enter without completing the expression, and the second one is the one that you added as a margin for the multiline string. When the stripMargin method finds those margin characters, it strips out the leading whitespaces. I find multiline strings helpful when creating data sets for unit tests.

String interpolation

Scala 2.10 has support for String interpolation. You can use the feature like this:

scala> val name = "Nilanjan"
name: String = Nilanjan
scala> s"My name $name"
res0: String = My name Nilanjan

Here is a method invoked on a class StringContext by passing the string literal contained within the double quotes. Any token prefixed with $ or wrapped with ${...} within the string will be replaced with its corresponding values. Similarly prepending f to any string literal allows the creation of simple formatted strings, similar to printf in other languages:

scala> val height = 1.9d
height: Double = 1.9
scala> val name = "James"
name: String = James
scala> println(f"$name%s is $height%2.2f meters tall")
James is 1.90 meters tall

As a careful reader, you’re probably a little surprised by this stripMargin method because I said that a Scala String object is nothing but a representative of a java.lang.String object; where did we get this new stripMargin method? There’s no method called stripMargin in java.lang.String. Again Predef is doing a little bit of magic by wrapping java.lang.String to another type called scala.collection.immutable.StringLike. If you look up the Scala documentation,[3] you’ll see the stripMargin method with many other useful methods that Scala provides to string objects, along with the ones defined in the java.lang.String class.

3 Documentation for the Scala standard library, www.scala-lang.org/api/current/index.html.

RichString vs. StringLike

If you’ve used previous versions of Scala, you’ll recall an earlier class called scala.RichString that provided additional methods to Scala string objects, but from Scala 2.8 it’s called scala.collection.immutable.StringLike. Treating a string as an immutable collection makes sense because it’s a collection of characters, and a string is an immutable object. Scala still has Rich type wrappers for other basic types like RichInt, RichBoolean, RichDouble, and so on.

XML Literals

Typically, working with XML means using third-party parsers and libraries, but in Scala it’s part of the language. Scala supports XML literals, where you can have XML fragments as part of the code:

val book = <book>
           <title>Scala in Action</title>
           <author>Nilanjan Raychaudhuri</author>
           </book>

When you type this expression into the Scala interpreter, you’ll get the following:

book: scala.xml.Elem =
    <book>
       <title>Scala in Action</title>
       <author>Nilanjan Raychaudhuri</author>
  </book>

Scala converts the XML literal to a scala.xml.Elem type object. It doesn’t stop here. You can put valid Scala code inside curly braces, {}, within the XML tags, and it works out great when you have to generate the XML dynamically:

scala> val message = "I didn't know xml could be so much fun"
scala> val code = "1"
scala> val alert = <alert>
            <message priority={code}>{message}</message>
            <date>{new java.util.Date()}</date>
            </alert>

alert: scala.xml.Elem =
<alert>
       <message priority="1">
            I didn't know xml could be so much fun
        </message>
       <date>Fri Feb 19 19:18:08 EST 2010</date>
 </alert>

As you can see, Scala executes the code inside the curly braces and replaces it with the output of the code. The code defined within curly braces is called Scala code blocks.

When using Scala code to generate attribute values, make sure you don’t put double quotes around it (priority={code}) because if you do, Scala will ignore it and treat it as a string value. Throughout the book you’ll look into various uses of XML literals and other XML goodies supported by Scala.

2.2.2. Defining variables

You’ve already seen many examples about defining variables. In Scala there are two ways you can define variables: val and var. A val is a single assignment variable, sometimes called value. Once initialized a val can’t be changed or reassigned to some other value (similar to final variables in Java). On the other hand, var is reassignable; you can change the value of the variable over and over again after initial assignment:

scala> val constant = 87
constant: Int = 87

scala> constant = 88
<console>:5: error: reassignment to val
       constant = 88
                ^
scala> var variable = 87
variable: Int = 87

scala> variable = 88
variable: Int = 88

The Scala interpreter does a good job of inferring the type of variable based on the value, but there are times when you’d like to, or have to, specify the type. You can specify the type of variable after the variable name, separating it by a colon (:).

There’ll be situations where you want to declare a variable without assigning a value because you don’t yet know the value. In cases like these you can use the Scala placeholder character (_) to assign a default value:

scala> var willKnowLater:String = _
willKnowLater: String = null

Because the default value for String is null, in this example the value of willKnowLater is null. As an exercise, try using Scala placeholder characters with other basic types and see what values you get back. One point to note here is that when declaring variables (both val and var), you have to specify the value or _ (Scala placeholder); otherwise, the Scala interpreter will complain. The only case where you can have variables (only vars because val always needs a value when declared) without values assigned to them is when the variables are declared inside a class.

Sometimes you may want to declare a type whose value gets calculated based on some time-consuming operation, and you don’t want to do that when you declare the variable; you want to initialize it lazily because by default Scala evaluates the value assigned to var or val when it’s declared. To change this default behavior, use lazy val:

scala> lazy val forLater = someTimeConsumingOperation()
forLater: Unit = <lazy>

The someTimeConsumingOperation() will be called when the variable forLater is used in any expression. Here’s another example that demonstrates the laziness:

scala> var a = 1
a: Int = 1

scala> lazy val b = a + 1
b: Int = <lazy>

scala> a = 5
a: Int = 5


scala> b
res1: Int = 6

In the last line, typing b forces the evaluation of the b, and because it wasn’t evaluated when b was declared, it uses the latest value of a. The lazy keyword is allowed only with val; you can’t declare lazy var variables in Scala.

The variable declaration can sometimes have a pattern on the left side. Say you want to extract the first element of a List and assign it to a variable. You can do that using a pattern on the left side along with the variable declaration:

scala> val first :: rest = List(1, 2, 3)
first: Int = 1
rest: List[Int] = List(2, 3)

List is an immutable sequence type of collection (similar to List in Java and C#) in Scala, and in this case it holds a collection of integers from 1 to 3. The pattern on the left side matches the first element of the List, in this case 1, to the variable first and the rest to the tail of the list, 2 and 3. The :: (called cons) is a method defined in List. I cover more about pattern matching later in this chapter.

Earlier I made the argument for immutability and why you should always prefer immutability to mutability. Keeping that in mind, always start with val when declaring variables in Scala and change to var when it’s absolutely necessary.

2.2.3. Defining functions

Functions are building blocks in Scala, and in this section you’re going to explore that topic. To define a function in Scala, use the def keyword followed by the method name, parameters, optional return type, =, and the method body. Figure 2.1 shows the syntax of the Scala function declaration.

Figure 2.1. The syntax of the Scala function declaration

Use a colon (:) to separate the parameter list from the return type. Multiple parameters are separated by commas (,). The equals sign (=) is used as a separator between the method signature and the method body.

Let’s drop the parameter for the time being; you’ll come back to parameters later. You’ll create your first Scala function without parameters:

scala> def myFirstMethod():String = { "exciting times ahead" }
myFirstMethod: ()String

The return type of a Scala function is optional because Scala infers the return type of a function automatically. There are situations where it doesn’t work, but don’t worry about that until later. Improve the myFirstMethod method by removing the return type:

scala> def myFirstMethod() = { "exciting times ahead" }
myFirstMethod: ()java.lang.String

scala> myFirstMethod()
res6: java.lang.String = exciting times ahead

The significance of = after the method signature isn’t only to separate the signature from the method body but also to tell the Scala compiler to infer the return type of your function. If you omit that, Scala won’t infer your return type:

scala> def myFirstMethod(){ "exciting times ahead" }
myFirstMethod: ()Unit

scala> myFirstMethod()

In this case when you invoke the function using the function name and (), you’ll get no result. In the REPL output, notice that the return type of your function is no longer java.lang.String; it’s Unit. Unit in Scala is like void in Java, and it means that the method doesn’t return anything.

Tip

Scala type inference is powerful, but use it carefully. If you’re creating a library and plan to expose your functions as a public API, it’s a good practice to specify the return type for the users of the library. In any case, if you think it’s not clear from the function what its return type is, either try to improve the name so that it communicates its purpose better or specify the return type.

Your myFirstMethod is simple: it returns the string "exciting times ahead" and when you have a function like that, you also drop the curly braces from the method body:

scala> def myFirstMethod() = "exciting times ahead"
myFirstMethod: ()java.lang.String

If you invoke the function, you’ll get the same result. In Scala it’s always possible to take out unnecessary syntax noise from the code. Because you aren’t passing any parameters, you can take out the unused () from the declaration, and it almost looks like a variable declaration, except that instead of using var or val you’re using def:

scala> def myFirstMethod = "exciting times ahead"
myFirstMethod: java.lang.String

When calling the function you can also leave out the parentheses:

scala> myFirstMethod
res17: java.lang.String = exciting times ahead

If the function has side effects, the common convention is to use “()” even though it isn’t required.

Returning to function parameters, the following function called max takes two parameters and returns the one that’s the greater of the two:

scala> def max(a: Int, b: Int) = if(a > b) a else b
max: (a: Int,b: Int)Int

scala> max(5, 4)
res8: Int = 5

scala> max(5, 7)
res9: Int = 7

By now you probably have figured out that specifying return is optional in Scala. You don’t have to specify the return keyword to return anything from the function. It will return the value of the last expression. In the previous case, if the if condition evaluates to true, then a is the last expression that is executed, so a is returned; otherwise b is returned. Even though the return type is optional, you do have to specify the type of the parameters when defining functions. Scala type inference will figure out the type of parameters when you invoke the function but not during the function declaration.[4],[5]

4 “Type inference,” Wikipedia, http://mng.bz/32jw.

5 Daniel Spiewak, posted at Code Commit, “What is Hindley-Milner? (and why is it cool?),” undated, http://mng.bz/H4ip.

Type inference

If you have a background in Haskell, OCaml, or any other type of inferred programming language, the way Scala parameters are defined could feel a bit weird. The reason is that Scala doesn’t use the Hindley-Milner algorithm to infer type; instead Scala’s type inference is based on declaration-local information, also known as local type inference. Type inference is out of the scope of this book, but if you’re interested you can read about the Hindley-Milner type inference algorithm and why it’s useful.

Sometimes it becomes necessary to create a function that will take an input and create a List from it. But the problem is you can’t determine the type of input yet. Someone could use your function to create a List of Int, and another person could use it to create a List of String. In cases like this you create a function in Scala by parameterized type. The parameter type will be decided when you invoke the function:

scala> def toList[A](value:A) = List(value)
toList: [A](value: A)List[A]

scala> toList(1)
res16: List[Int] = List(1)

scala> toList("Scala rocks")
res15: List[java.lang.String] = List(Scala rocks)

When declaring the function, you denote the unknown parameterized type as A. Now when your toList is invoked, it replaces the A with the parameter type of the given parameter. In the method body you create an instance of immutable List by passing the parameter, and from the REPL output it’s clear that List is also using a parameterized type.

Note

If you’re a Java programmer, you’ll find lots of similarities between Java generics and Scala parameterized types. The only difference to remember for now is that Java uses angle brackets (<>) and Scala uses square brackets ([]). Another Scala convention for naming the parameterized types is that they normally start at A and go up to Z as necessary. This contrasts with the Java convention of using T, K, V, and E.

Function Literals

In Scala you can also pass a function as a parameter to another function, and most of the time in those cases I provide an inline definition of the function. This passing of functions as a parameter is sometimes loosely called closure (passing a function isn’t always necessarily closure; you’ll look into that in chapter 4). Scala provides a shorthand way to create a function in which you write only the function body, called function literals. Put that to a test. In this test you want to add all the elements of a List using function literals. This demonstrates a simple use of function literals in Scala. Here you’re creating a List of even numbers:

scala> val evenNumbers = List(2, 4, 6, 8, 10)
evenNumbers: List[Int] = List(2, 4, 6, 8, 10)

To add all the elements of List (scala.collection.immutable.List), you can use the foldLeft method defined in List. The foldLeft method takes two parameters: an initial value and a binary operation. It applies the binary operation to the given initial value and all the elements of the list. It expects the binary operation as a function that takes two parameters of its own to perform the operation, which in our case will be addition. If you can create a function that will take two parameters and add them, you’re finished with the test. The foldLeft function will call your function for every element in the List, starting with the initial value:

scala> evenNumbers.foldLeft(0) { (a: Int, b:Int) => a + b }
res19: Int = 30

In this case the function (a: Int, b:Int) => a + b is called an anonymous function, or a function without a predefined name. You can improve your function by taking advantage of Scala’s type inference:

scala> evenNumbers.foldLeft(0) { (a, b) => a + b }
res20: Int = 30

Usually you have to specify the type of the parameter for top-level functions because Scala can’t infer the parameter types when declared, but for anonymous functions Scala inference can figure out the type from the context. In this case you’re using a list of integers and 0 as your initial value, and based on that Scala can easily infer the type of a and b as an integer. Scala allows you to go even further with your anonymous function: you can drop the parameters and only have the method body to make it a function literal. But in this case the parameters will be replaced with underscores (_). An underscore has a special meaning in Scala, and in this context it’s a placeholder for a parameter; in your case, use two underscores:

scala> evenNumbers.foldLeft(0) { _ + _ }
res21: Int = 30

Each underscore represents a parameter in your function literal. You’ve already seen another use of the underscore when assigning a default value to variables. In Scala you can use underscores in various places, and their meaning is determined solely by the context and where they’re used. Sometimes it gets a little confusing, so always remember that the value of the underscore is based on where it’s being used. You’ll see other uses of underscores throughout the book. Function literals are a common idiom in Scala, and you’ll find occurrences of them in Scala libraries and codebases.

In chapter 1 you saw the following example but without enough explanation of what’s going on with the code. Now, with your new knowledge of function literals, it should be pretty obvious that _.isUpper is a function literal:

val hasUpperCase = name.exists(_.isUpper)

In this case you’re invoking the given function literals for each character in the name string; when it finds an uppercase character, it will exit. The underscore in this context represents a character of name string.

Using Scala Closure and First-Class Functions: An Example

Before moving to the next section, leaving the “defining function” section without a small working example of closure would be unfair. A closure is any function that closes over the environment in which it’s defined. For example, closure will keep track of any variable changes outside the function that are being referred to inside the function.

In the example you’ll try to add support for the word break. I haven’t talked about Scala keywords yet, but Scala doesn’t have break or continue. Once you get comfortable with Scala, you won’t miss them because Scala’s support of functional programming style reduces the need for break or continue. But assume you have a situation where you think having break would be helpful. Scala is an extensible programming language, so you can extend it to support break.

Use the Scala exception-handling mechanism to implement break in Scala. Throwing an exception will help you break the sequence of execution, and the catch block will help you reach the end of the call. Because break isn’t a keyword, you can use it to define your function so that it will throw an exception:

def break = new RuntimeException("break exception")

Another subject not yet covered is exception handling, but if you’ve used it in Java, C#, or Ruby, it should be easy to follow. In any case, you’ll read about exception handling in a later part of the chapter. Now create the main function that will take the operation that needs a breakable feature. Make it obvious and call it breakable:

def breakable(op: => Unit) { ... }

What’s this op: => Unit? The special right arrow (=>) lets Scala know that the breakable function expects a function as a parameter. The right side of the => defines the return type of the function—in this case it’s Unit (similar to Java void)—and op is the name of the parameter. Because you haven’t specified anything on the left side of the arrow, it means that the function you’re expecting as a parameter doesn’t take any parameter for itself. But if you expect a function parameter that takes two parameters, such as foldLeft, you have to define it as follows:

def foldLeft(initialValue: Int, operator: (Int, Int) => Int)= { ... }

The breakable function that you declared takes a no-parameter function and returns Unit. Now, using these two functions, you could simulate the break. Let’s look at an example function that needs to break when the environment variable SCALA_HOME isn’t set; otherwise, it must do the work:

def install = {
  val env = System.getenv("SCALA_HOME")
  if(env == null) break
  println("found scala home lets do the real work")
}

Now inside the breakable function we need to catch the exception that will get raised when break is called from the install function:

try {
    op
} catch { case _ => }

That’s it. The following listing holds the complete code.

Listing 2.1. breakable, break, and install functions
val breakException = new RuntimeException("break exception")

def breakable(op: => Unit) {
  try {
    op
  } catch { case _ => }
}

def break = throw breakException

def install = {
  val env = System.getenv("SCALA_HOME")
  if(env == null) break
  println("found scala home lets do the real work")
}

To invoke the breakable function, pass the method name that needs a breakable feature, like breakable(install)—or you can inline the install function and pass it as a closure:

breakable {
  val env = System.getenv("SCALA_HOME")
  if(env == null) break
  println("found scala home lets do the real work")
}

In Scala if the last argument of a function is of function type, you can pass it as closure. This syntax sugar is useful in creating DSLs. In the next chapter you’ll look into how closures are converted into objects; remember, everything in Scala is an object.

Note

Scala already provides breakable as part of the library. Look for scala.util.control.Breaks. You should use Breaks if you have a need for break. Again, I’d argue that once you look into functional programming with Scala in detail, you’ll probably never have a need for break.

2.3. Working with Array and List

Chapter 4 is dedicated to data structures, but until then I’ll introduce List and Array so you can start writing useful Scala scripts.

In Scala, array is an instance of the scala.Array class and is similar to the Java array:

scala> val array = new Array[String](3)
array: Array[String] = Array(null, null, null)

scala> array(0) = "This"

scala> array(1) = "is"

scala> array(2) = "mutable"

scala> array
res37: Array[String] = Array(This, is, mutable)

Always remember that in Scala the type information or parameterization is provided using square brackets. The type parameterization is a way to configure an instance with type information when creating the instance.

Now iterating through each element in the array is easy; call the foreach method:

scala> array.foreach(println)
This
is
mutable

You’re passing a function literal to the foreach method to print all the elements in the array. There are other useful methods defined for Array objects; for a complete list look in Scaladoc for scala.collection.mutable.ArrayLike. The most obvious question in your mind right now is probably why we have to check ArrayLike, which is a different class than the Array used to check methods that are available for an Array instance in Scala. The answer is Predef. Scala Predef provides additional array functionality dynamically using ArrayLike when you create an instance of an Array. Again, Predef is a great place to start to understand the Scala Library.

Note

Predef implicitly converts Array to scala.collection.mutable.ArrayOps. ArrayOps is the subclass of ArrayLike, so ArrayLike is more like the interface for all the additional methods available to Array type collections.

When writing Scala scripts, you sometimes have to take command-like arguments. You can do that implicitly as a val type variable called args. In the following example you’ll create a Scala script that takes input from a user and prints it to the console:

args.foreach(println)

Open your favorite editor and save this line in a file called myfirstScript.scala. Open a command prompt to the location where the file is saved and run the following command:

scala myfirstScript.scala my first script

You’ll see the following output:

my
first
script

You executed your first script. You’re using the same command you used to start the Scala REPL environment. But in this case you’re executing a Scala script by specifying the script filename and three parameters: my, first, and script. You’ll see another script example at the end of this chapter.

The Array is a mutable data structure; by adding each element to the array, you’re mutating the array instance and producing a side effect. In functional programming, methods should not have side effects. The only effect a method is allowed to have is to compute a value and return that value without mutating the instance. An immutable and more functional alternative to a sequence of objects like Array is List. In Scala, List is immutable and makes functional-style programming easy. Creating a list of elements is as easy as the following:

scala> val myList = List("This", "is", "immutable")
myList: List[java.lang.String] = List(This, is, immutable)

The List is shorthand for scala.collection.immutable.List, and again Predef automatically makes it available to you:

scala> val myList = scala.collection.immutable.List("This", "is",
     "immutable")
myList: List[java.lang.String] = List(This, is, immutable)
What is this scala.collection.immutable.$colon$colon?

If you call the getClass method on myList to see what type of object it is, you might be surprised. Instead of scala.collection.immutable.List, you’ll see

scala> myList.getClass
res42: java.lang.Class[_] = class
     scala.collection.immutable.$colon$colon

That’s because scala.collection.immutable.List is an abstract class, and it comes with two implementations: the scala.Nil class and scala.::. In Scala, :: is a valid identifier, and you could use it to name a class. Nil represents an empty list, and scala.:: represents any nonempty list.

Most of us are used to mutable collections where, when we add or remove elements, the collection instance expands or shrinks (mutates), but immutable collections never change. Instead, adding or removing an element from an immutable collection creates a new modified collection instance without modifying the existing one. The following example adds an element to an existing List:

scala> val oldList = List(1, 2)
oldList: List[Int] = List(1, 2)

scala> val newList = 3 :: oldList
newList: List[Int] = List(3, 1, 2)

scala> oldList
res45: List[Int] = List(1, 2)

In this example you’re adding 3 to an existing List containing elements 1 and 2 using the :: method. The job of the :: method is to create a new List with all the existing elements plus the new element added at the front of the List. To add at the end of the List, invoke the :+ method:

scala> val newList = oldList :+ 3
newList: List[Int] = List(1, 2, 3)

Scala provides a special object called Nil to represent an empty List, and you can use it to create new lists easily:

scala> val myList = "This" :: "is" :: "immutable" :: Nil
myList: List[java.lang.String] = List(This, is, immutable)

In this example you’re using a new instance of List every time you add an element. To delete an element from a List, you could use the - method, but it’s deprecated. A better way would be to use the filterNot method, which takes a predicate and selects all the elements that don’t satisfy the predicate. To delete 3 from the newList, you can do something like the following:

scala> val afterDelete = newList.filterNot(_ == 3)
afterDelete: List[Int] = List(1, 2)

You’ll delve deeper into Scala collections in chapter 4, section 4.3, but for now you know enough to play with Scala and script a few things. In the meantime I encourage you to look into methods defined for List and play with them.

2.4. Controlling flow with loops and ifs

It’s a little hard to get into useful programming or scripting with Scala without the loops and ifs. Well, your wait is over. In Scala, if and else blocks work as they do in any other programming language. If the expression inside the if evaluates to true, then the if block gets executed; otherwise, the else block is executed. The interesting part about Scala is that every statement is an expression, and its value is determined by the last expression within the statement. Assigning a value depending on some condition in Scala could look like this:

val someValue = if(some condition) value1 else value2

scala> val useDefault = false
useDefault: Boolean = false

scala> val configFile = if(useDefault) "custom.txt" else "default.txt"
configFile: java.lang.String = default.txt

Scala doesn’t support the ? operator as Java does, but I don’t think you’ll miss it in Scala. You can nest if/else blocks, and you can combine multiple if/else blocks using else if.

Loops in Scala have all the usual suspects like the while loop and do-while, but the most interesting looping construct is for or for-comprehensions. The while and do-while loops are pretty standard, and in Scala they aren’t any different from Java or C#. The next section looks at Scala for-comprehensions.

2.5. For-comprehensions

A for-comprehension in Scala is like a Swiss Army knife: you can do many things with it using basic simple elements. The for expression in Scala consists of a for keyword followed by one or more enumerators surrounded by parentheses and followed by an expression block or yield expression (see figure 2.2).

Figure 2.2. The syntax of a for-comprehension

Before I go into yield expression, let’s look into the more traditional form of the for loop. The common pattern used in a for loop is to iterate through a collection. To print all the files in a directory that end with the .scala extension, for example, you have to do something like the following:

val files = new java.io.File(".").listFiles
for(file <- files) {
    val filename = file.getName
    if(fileName.endsWith(".scala")) println(file)
}

The only thing that looks different from for loops in Java or C# is the expression file <- files. In Scala this is called a generator, and the job of a generator is to iterate through a collection. The right side of the <- represents the collection—in this case, files. For each element in the collection (file in this case) it executes the for block. This is similar to the way you define a for loop in Java:

for(File file: files) {
      String filename = file.getName();
      if(filename.endsWith(".scala")) System.out.println(file);
}

In the case of Scala, you don’t have to specify the type of file object because Scala type inference will take care of it.

Apart from the generator, you can use other ingredients in a Scala for loop to simplify the previous example.

for(
    file <- files;
    fileName = file.getName;
    if(fileName.endsWith(".scala"))
) println(file)

Scala for loops allow you to specify definitions and guard clauses inside the loop. In this case you’re defining a filename variable and checking whether the filename ends with .scala. The loop will execute when the given guard clause is true, so you’ll get the same result as the previous example. Note that all the variables created inside a for expression are of the val type, so they can’t be modified and hence reduce the possibility of side effects.

As mentioned earlier, it’s possible to specify more than one generator in a Scala for loop control. The following example executes the loop for each generator and adds them:

scala> val aList = List(1, 2, 3)
aList: List[Int] = List(1, 2, 3)

scala> val bList = List(4, 5, 6)
bList: List[Int] = List(4, 5, 6)

scala> for { a <- aList; b <- bList } println(a + b)
5
6
7
6
7
8
7
8
9

The generators in this case are aList and bList, and when you have multiple generators, each generator is repeated for the other generator. When a = 1 for each value of b, that is, b = 4, b = 5, b = 6, the loop will be executed, and so on. I used curly braces to surround the for expression, but you don’t have to; you could use (). I tend to use curly braces when I have more than one generator and guard clause.

The for-comprehension in Scala comes in two flavors. You’ve already seen one form in the previous examples: the imperative form. In this form you specify the statements that will get executed by the loop, and it doesn’t return anything. The other form of for-comprehension is called the functional form (sometimes it’s also called sequence comprehension). In the functional form, you tend to work with values rather than execute statements, and it does return a value. Look at the same example in functional form:

scala> for { a <- aList; b <- bList } yield a + b
res27: List[Int] = List(5, 6, 7, 6, 7, 8, 7, 8, 9)

Instead of printing the value of a + b, you’re returning the value of the addition from the loop using the yield keyword. You’re using the same aList and bList instances in the loop control, and it returns the result as a List. Now if you want to print the result, as in the previous example, you have to loop through the result List:

scala> val result = for { a <- aList; b <- bList } yield a + b
result: List[Int] = List(5, 6, 7, 6, 7, 8, 7, 8, 9)

scala> for(r <- result) println(r)
5
6
7
6
7
8
7
8
9

It does look like the functional form is more verbose than the imperative form, but think about it. You’ve separated the computation (the adding of two numbers) from how you’re using it—in this case, printing the result. This improves the reusability and compatibility of functions or computations, which is one of the benefits of functional programming. In the following example you reuse the result produced by the for-yield loop to create an XML node:

scala> val xmlNode = <result>{result.mkString(",")}</result>
xmlNode: scala.xml.Elem = <result>5,6,7,6,7,8,7,8,9</result>

The mkString is a method defined in scala.collection.immutable.List. It takes each element in the List and concatenates each element with whatever separator you provide—in this case, a comma. Even though it doesn’t make sense, what if you try to print inside the yield expression? What will happen? Remember, everything in Scala is an expression and has a return value. If you try the following, you’ll still get a result, but the result won’t be useful because it will be a collection of units. A unit is the equivalent of void in Java, and it’s the result value of a println function used inside the yield expression:

scala> for { a <- aList; b <- bList } yield { println(a+b)}
5
6
7
6
7
8
7
8
9
res32: List[Unit] = List((), (), (), (), (), (), (), (), ())

You’ve only scratched the surface of for-comprehension, and I come back to this in chapter 4 to examine functional data structures, so hold on to your inquisitiveness until chapter 4 (or jump to that chapter). The next section moves into another functional concept: pattern matching.

2.6. Pattern matching

Pattern matching is another functional programming concept introduced in Scala. To start with, Scala pattern matching looks similar to switch case in Java. The example in the following listing, showing the similarity between Scala and Java, takes an integer and prints its ordinal number.

Listing 2.2. An ordinal class written in Java

Here the argument of the program is parsed to the integer value, and the ordinal method returns the ordinal text of a given number. Right now, it only knows how to handle numbers from 1 to 10. The following listing shows the same example in Scala.

Listing 2.3. An ordinal class in Scala

Here you’re doing something similar to the previous Java example: taking an input integer value from a command like args and determining the ordinal value of the number. Because Scala can also be used as a scripting language, you don’t have to define an entry point like the main method. And you no longer need to provide a break for each case because in Scala you can’t overflow into other case clauses (causing multiple matches) as in Java, and there’s no default statement. In Scala, default is replaced with case _ to match everything else. To run the Ordinal.scala script, execute the following command from a command prompt:

scala Ordinal.scala <your input>

The wildcard case is optional and works like a safe fallback option. If you remove it, and none of the existing cases match, you get a match error:

scala> 2 match { case 1 => "One" }
scala.MatchError: 2
    at .<init>(<console>:5)
    at .<clinit>(<console>)
  ...

This is great because it tells you that you’re missing a case clause, unlike in Java, where if you remove the default and none of the existing cases match, it ignores it without providing any sort of feedback.

The similarity between Java and Scala pattern matching ends here because Scala takes pattern matching to the next level. In Java you can only use a switch statement with primitives and enums, but in Scala you can pattern match strings and complex values, types, variables, constants, and constructors. More pattern-matching concepts are in the next chapter, particularly constructor matching, but look at an example of a type match. The following example defines a method that takes an input and checks the type of the given object:

def printType(obj: AnyRef) = obj match {
  case s: String => println("This is string")
  case l: List[_] => println("This is List")
  case a: Array[_] => println("This is an array")
  case d: java.util.Date => println("This is a date")
}

In this example you’re using a Scala type pattern consisting of a variable and a type. This pattern matches any value matched by the type pattern—in this case, String, List[AnyRef], Array[AnyRef], and java.util.Date. When the pattern matches with the type, it binds the variable name to the value. You could do that in Java using the instanceof operator and casting, but this is a more elegant solution. Save this method into the file printType.scala and load the file into the Scala REPL:

scala> :load printType.scala
Loading printType.scala...
printType: (obj: AnyRef)Unit

Now try a printType function with various types of input:

scala> printType("Hello")
This is string

scala> printType(List(1, 2, 3))
This is List

scala> printType(new Array[String](2))
This is an array

scala> printType(new java.util.Date())
This is a date

Scala also allows the infix operation pattern, in which you can specify an infix operator in your pattern. In the infix style, operators are written between the operands—for example, 2 + 2. In the following example, you’re extracting the first and the second elements from the List:

scala> List(1, 2, 3, 4) match {
        case f :: s :: rest => List(f, s)
        case _ => Nil
      }
res7: List[Int] = List(1, 2)

Here you’re matching 1 to f, 2 to s, and 3 and 4 to the rest of the variables. Think of it as what it will take to create a List of 1, 2, 3, and 4 from the expression f :: s :: rest, and then this will make more sense.

Sometimes you need to have a guard clause along with the case statement to have more flexibility during pattern matching. In the following example you’re determining the range in which the given number belongs:

def rangeMatcher(num:Int) = num match {
  case within10 if within10 <= 10 => println("with in 0 to 10")
  case within100 if within100 <= 100 => println("with in 11 to 100")
  case beyond100 if beyond100 < Integer.MAX_VALUE => println("beyond 100")
}

With this new information, revisit the ordinal problem. The previous Scala ordinal example supported only 1 to 10, but the following listing implements that for all integers.

Listing 2.4. Ordinal2.scala reimplemented
val suffixes = List(
      "th", "st", "nd", "rd", "th", "th", "th", "th", "th",
th")
println(ordinal(args(0).toInt))

def ordinal(number:Int) = number match {
  case tenTo20 if 10 to 20 contains tenTo20 => number + "th"
  case rest => rest + suffixes(number % 10)
}

Here in the new implementation of ordinal you’re using range, which is a collection of integer values between a given start and end. The expression 10 to 20 is 10.to(20) (remember that methods can be used as infix operators). You’re calling the to method in RichInt, and it creates an inclusive range (scala.collection.immutable.Inclusive). You’re calling the contains method on the range to check whether the number belongs to the range. In the last case you’re mapping all the numbers below 10 and beyond 20 to a new variable called rest. This is called variable pattern matching in Scala. You can access elements of a List like array using index positions in the List. You’ll revisit pattern matching in chapter 3 after looking at case classes. It’s time to move on to the last topic of this chapter: exception handling.

2.7. Exception handling

You caught a glimpse of Scala exception handling in the breakable example. Scala’s exception handling is little different from Java’s. Scala allows you a single try/catch block, and in the single catch block you can use pattern matching to catch exceptions. The catch block is a match block under the surface, so all the pattern-matching techniques that you learned in the previous section are applicable to a catch block. Modify the rangeMatcher example to throw an exception when it’s beyond 100:

def rangeMatcher(num:Int) = num match {
  case within10 if within10 <= 10 => println("with in 0 to 10")
  case within100 if within100 <= 100 => println("with in 11 to 100")
  case _ => throw new IllegalArgumentException(
            "Only values between 0 and 100 are allowed")
}

Now when calling this method you can surround it with a try/catch block and catch the exception:

scala> try {
          rangeMatcher1(1000)
      } catch { case e: IllegalArgumentException => e.getMessage }
res19: Any = Only values between 0 and 100 are allowed

The case statement isn’t any different from the type pattern matching used in the printType example.

Scala doesn’t have any concept like a checked exception; all exceptions are unchecked. This way is more powerful and flexible because as a programmer you’re free to decide whether or not you want to catch an exception. Even though Scala exception handling is implemented differently, it behaves exactly like Java, with exceptions being unchecked, and it allows Scala to easily interoperate with existing Java libraries. You’ll see the use of Scala exception handling in examples throughout the book.

2.8. Command-line REST client: building a working example

You’ve looked into a number of interesting concepts about Scala in this chapter, and it’ll be nice to see some of these concepts in action together. In this section you’ll build a command-line-based REST client in Scala script. You’re going to use the Apache HttpClient[6] library to handle HTTP connections and various HTTP methods.

6 “HttpClient Overview,” July 3, 2012, http://mng.bz/Q4Bf.

What is REST?

REST stands for REpresentational State Transfer. It’s software architectural style for distributed hypermedia systems like the World Wide Web. The term first appeared in “Architectural Styles and the Design of Network based Software Architectures,”[7] the doctoral dissertation paper by Roy Fielding, one of the principal authors of the HTTP specification.

7 Roy Thomas Fielding, “Architectural Styles and the Design of Network-based Software Architectures,” doctoral dissertation, University of California, Irvine, 2000. http://mng.bz/2Xa4.

REST strictly refers to the collection of architectural principles[8] mentioned here. Systems that follow Fielding’s REST principles are often referred to as RESTful.

8 Roy T. Fielding and Richard N. Taylor, “Principled Design of the Modern Web Architecture,” University of California, Irvine, 2000, http://mng.bz/188g.

  • Application state and functionality are divided into resources.
  • Every resource is uniquely addressable using a universal syntax.
  • All resources share a uniform interface for transfer of state between client and resource, consisting of well-defined operations (GET, POST, PUT, DELETE, OPTIONS, and so on, for RESTful web services) and content types.
  • A protocol that’s client/server, stateless cacheable, and layered.

To make a REST call to a RESTful service, you have to be aware of the operations supported by the service. To test your client you need a RESTful web service. You could use free public web services to test the client, but to have better control of the operations on the service you’ll create one. You could use any REST tool or a framework to build the REST service. I’ll use a Java servlet (Java developers are familiar with it) to build the service to test the REST client. Understanding how the service is implemented isn’t important for this example.

The simple way to create a RESTful service for now is to use a Java servlet, as shown in the following listing.

Listing 2.5. Java servlet as a RESTful service

In the servlet you’re supporting three HTTP methods: GET, POST, and DELETE. These methods are simple and return the request parameters and headers in response, which is perfect when testing your REST client. The two helper methods I added are parameters and headers. The parameters method is responsible for parsing the HTTP request object for parameters that are passed from the client; in this case, it’s the REST client. The headers method retrieves all the header values from the request object. Once the servlet is built, you must deploy the WAR file to a Java web container.

I’ve used Maven and Jetty[9] to build and run[10] the Java servlet, but you’re free to use any Java web container.

9 Getting started with Jetty: http://wiki.eclipse.org/Jetty/Howto.

10 Jan Bartel, editor, “Maven Jetty Plugin Configuration Guide,” Nov. 30, 2011, http://mng.bz/3ubj.

2.8.1. Introducing HttpClient library

HttpClient is a client-side HTTP transport library. The purpose of HttpClient is to transmit and receive HTTP messages. It’s not a browser, and it doesn’t execute JavaScript or try to guess the content type or other functionality unrelated to the HTTP transport. The most essential function of HttpClient is to execute HTTP methods. Users are supposed to provide a request object like HttpPost or HttpGet, and the HttpClient is expected to transmit the request to the target server and return the corresponding response object, or throw an exception if the execution is unsuccessful.

HttpClient encapsulates each HTTP method type in an object, and they’re available under the org.apache.http.client.methods package. In this script you’re going to use four types of requests: GET, POST, DELETE, and OPTIONS.[11] The previous example implemented only GET, POST, and DELETE because the web container will automatically implement the OPTIONS method. HttpClient provides a default client and is good enough for our purpose. To execute an HTTP DELETE method you have to do the following:

11 HTTP method definitions, http://mng.bz/9qso.

val httpDelete = new HttpDelete(url)
val httpResponse = new DefaultHttpClient().execute(httpDelete)

The HTTP POST method is a little different because, according to the HTTP specification, it’s one of the two entity-enclosing methods. The other one is PUT. To work with entities HttpClient provides multiple options, but in the example you’re going to use the URL-encoded form entity. It’s similar to what happens when you POST a form submission. Now you can dive into building the client.

To use the HttpClient in your script, you have to import all the necessary classes. I haven’t talked about import, but for now think of it as similar to Java import except that Scala uses _ for importing all classes in a package, as in the following:

import org.apache.http._
import org.apache.http.client.entity._
import org.apache.http.client.methods._
import org.apache.http.impl.client._
import org.apache.http.client.utils._
import org.apache.http.message._
import org.apache.http.params._

You can do other interesting things with Scala imports, but that’s in the next chapter.

2.8.2. Building the client, step by step

Now, because the service is up and running, you can focus on the client script. To make the script useful, you have to know the type of operation (GET or POST), request parameters, header parameters, and the URL to the service. The request parameters and header parameters are optional, but you need an operation and a URL to make any successful REST call:

require(args.size >= 2,
"at minimum you should specify action(post, get, delete, options) and url")

val command = args.head
val params = parseArgs(args)
val url = args.last

You’re using a require function defined in Predef to check the size of the input. Remember that the command-line inputs are represented by an args array. The require function throws an exception when the predicate evaluates to false. In this case, because you expect at least two parameters, anything less than that will result in an exception. The first parameter to the script is the command, and the next ones are the request and header parameters. The last parameter is the URL. The input to the script will look something like the following:

post -d <comma separated name value pair>
      -h <comma separated name value pair> <url>

The request parameters and header parameters are determined by a prefix parameter, –d or –h. One way to define a parseArgs method to parse request and header parameters is shown in the following listing.

Listing 2.6. Parsing headers and parameters passed to the program
def parseArgs(args: Array[String]): Map[String, List[String]] = {

  def nameValuePair(paramName: String) = {
    def values(commaSeparatedValues: String) =
        commaSeparatedValues.split(",").toList

     val index = args.findIndexOf(_ == paramName)
    (paramName, if(index == -1) Nil else values(args(index + 1)))
  }

  Map(nameValuePair("-d"), nameValuePair("-h"))
}

This listing has defined a function inside another function. Scala allows nested functions, and nested functions can access variables defined in the outer scope function—in this case, the args parameter of the parseArgs function. Nested functions allow you to encapsulate smaller methods and break computation in interesting ways. Here the nested function nameValuePair takes the parameter name, –d or –h, and creates a list of name-value pairs of request or header parameters. The next interesting thing about the nameValuePair function is the return type. The return type is a scala.Tuple2, a tuple of two elements. Tuple is immutable like List, but unlike List it can contain different types of elements; in this case, it contains a String and a List. Scala provides syntax sugar for creating a Tuple by wrapping elements with parentheses ():

scala> val tuple2 = ("list of one element", List(1))
tuple2: (java.lang.String, List[Int]) = (list of one element,List(1))

This is similar to:

scala> val tuple2 = new scala.Tuple2("list of one element", List(1))
tuple2: (java.lang.String, List[Int]) = (list of one element,List(1))

Here’s how to create a tuple of three elements:

scala> val tuple3 = (1, "one", List(1))
tuple3: (Int, java.lang.String, List[Int]) = (1,one,List(1))

The last interesting thing I’d like to mention about the parseArgs method is the Map. A Map is an immutable collection of keys and values. Chapter 4 discusses Map in detail. In this example you’re creating a Map of parameter name(-d or –h) and listing all the parameters as values. When you pass a tuple of two elements to Map, it takes the first element of the tuple as the key and the second element as the value:

scala> val m = Map(("key1", "value1"), ("key2", "value2"))
m: scala.collection.immutable.Map[java.lang.String,java.lang.String] =
     Map(key1 -> value1, key2 -> value2)

scala> m("key1")
res8: java.lang.String = value1

For now you’ll support only four types of REST operations: POST, GET, DELETE, and OPTIONS, but I encourage you to implement other HTTP methods like PUT and HEAD. To check what type of operation is requested, you can use simple pattern matching:

command match {
  case "post"    => handlePostRequest
  case "get"     => handleGetRequest
  case "delete"  => handleDeleteRequest
  case "options" => handleOptionsRequest
}

Here handlePostRequest, handleGetRequest, handleDeleteRequest, and handle-OptionRequest are functions defined in the script. Each needs to be implemented a little differently. For example, in the case of a GET call, you’ll pass the request parameters as query parameters to the URL. POST will use a URL-encoded form entity to pass the request parameters. DELETE and OPTIONS won’t use any request parameters. Look at the handleGetRequest method, shown in the following listing.

Listing 2.7. Preparing a GET request and invoking the REST service
def headers = for(nameValue <- params("-h")) yield {
  def tokens = splitByEqual(nameValue)
  new BasicHeader(tokens(0), tokens(1))
}

def handleGetRequest = {
  val query = params("-d").mkString("&")
  val httpget = new HttpGet(s"${url}?${query}" )
  headers.foreach { httpget.addHeader(_) }
  val responseBody =
      new DefaultHttpClient().execute(httpget,
new BasicResponseHandler())
  println(responseBody)
}

In this method you’re retrieving all the request parameters from the Map params and creating the query string. Then you create the HttpGet method with the given URL and query string. The DefaultHttpClient is executing the httpget request and giving the response. The handlePostRequest method is a little more involved because it needs to create a form entity object, as shown in the following listing.

Listing 2.8. Preparing a POST request and invoking the REST service

Something interesting and unusual is going on here. First is the toJavaList method. The Scala List and the Java List are two different types of objects and aren’t directly compatible with each other. Because HttpClient is a Java library, you have to convert it to a Java type collection before calling the UrlEncodedFormEntity. The special :_* tells the Scala compiler to send the result of toArray as a variable argument to the Arrays.asList method; otherwise, asList will create a Java List with one element. The following example demonstrates that fact:

scala> val scalaList = List(1, 2, 3)
scalaList: List[Int] = List(1, 2, 3)

scala> val javaList = java.util.Arrays.asList(scalaList.toArray)
javaList: java.util.List[Array[Int]] = [[I@67826710]

scala> val javaList = java.util.Arrays.asList(scalaList.toArray:_*)
javaList: java.util.List[Int] = [1, 2, 3]

The following listing contains the complete RestClient.scala script.

Listing 2.9. RestClient.scala

In this complete example you implemented the support for four types of HTTP requests: POST, GET, DELETE, and OPTIONS. The require function call ensures that your script is invoked with at least two parameters: the action type and the URL of the REST service. The pattern-matching block at the end of the script selects the appropriate action handler for a given action name. The parseArgs function handles the additional arguments provided to the script, such as request parameters or headers, and returns a Map containing all the name-value pairs. The formEntity function is interesting because the URL encodes the request parameters when the http request type is POST, because in POST request parameters are sent as part of the request body and they need to be encoded.

To run the REST client you can use any build tool that can build Scala code. This example uses a build tool called simple build tool (SBT). You’ll learn about this tool in detail in chapter 6, but for now go ahead and install the tool following the instructions from the SBT wiki (http://www.scala-sbt.org). Take a look at the codebase for this chapter for an example.

2.9. Summary

This chapter covered most of the basic Scala concepts like data types, variables, and functions. You saw how to install and configure Scala. Most importantly, you learned how to define functions, an important building block in Scala, and functional concepts including pattern matching and for-comprehension. You also learned about exception handling and how Scala uses the same pattern-matching techniques for exception handling. This chapter also provided a basic introduction to List and Array collection types so you can start building useful Scala scripts. Chapter 4 covers Scala collections in detail. You worked with the Scala REPL throughout the chapter when trying out examples. The Scala REPL is an important and handy tool, and you’ll use it throughout the book. The chapter finished by building a complete REST client using most of the concepts you learned in it. The example also demonstrated the flexibility Scala provides when building scripts. It’s now time to move on to Scala classes and objects.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset