Scala Tutorial for Beginners
In this Tutorial article, we will see how to work with Scala Programming language, which is similar to Java but has got lot more advancements, as it was designed to overcome the pitfalls/shortcomings of Java programming language.
According to Wikipedia, the definition of Scala Programming language goes as follows.
Scala (SKAH-lah) is a general purpose programming language. Scala has full support for functional programming and a very strong static type system. Designed to be concise, many of Scala’s design decisions were inspired by criticism of the shortcomings of Java.
Scala source code is intended to be compiled to Java bytecode, so that the resulting executable code runs on a Java virtual machine. Java libraries may be used directly in Scala code and vice versa (language interoperability). Like Java, Scala is object-oriented, and uses a curly-brace syntax reminiscent of the C programming language. Unlike Java, Scala has many features of functional programming languages like Scheme, Standard ML and Haskell, including currying, type inference, immutability, lazy evaluation, and pattern matching.
Pre-requisite: The readers are expected to know the basics of Java Programming.
The following table shows an overview of the entire article:
Table of Contents
1. Environment
The examples in this article are executed in the Command Prompt / Shell with the Scala Interpreter. But they are guaranteed to work with any of the IDEs (like Eclipse – Scala IDE, IntelliJ IDEA etc.,) through the respective plugins. The examples are executed with the Scala Version: 2.11.7 in Windows 7.
Let us first download and install Scala in our desktop. To download the latest version of Scala for your Operating System, please refer this link. It is a straight forward installation like any other executable. You may please follow the instructions if any for your Operating System. This will set the %SCALA_HOME%/bin
directory of Scala to the PATH
environment variable, for us to start working with the Scala programs.
2. Hello World in Scala
Let us write some Scala code to see the typical, popular Hello, World
in Scala. We have two ways to do that. First is the Scala Interpreter which is a REPL, and another is the usual way of saving the code in a file and compiling and executing it afterwards. We will see both of them here.
2.1 Hello World in REPL Interpreter
Scala Interpreter is a REPL (Read-Evaluate-Print-Loop) Interpreter, in which you can execute the quick one liners and scripts without any underlying class structure as an accompanying barebone skeleton as in few of the programming languages like C, C++ and Java. This is an advantage for evaluating the programming language and its constructs thereby you can save time. You use this REPL interpterter for your instant results.
To be doubly sure, let us verify whether Scala installed in our machine correctly, by seeing the %SCALA_HOME%
environment variable.
C:\Users\Raghs> echo %SCALA_HOME% C:\Program Files (x86)\scala
As you see, Scala has been installed in the C:\Program Files (x86)\scala
directory successfully. This could vary in your machine depending on the type of Operating System you have.
2.1.1 Starting the Interpreter
For using this REPL interpreter, you need to open the Command Prompt/Terminal
and execute the command scala
. If your installation was successul and your PATH
environment variable has an entry to the %SCALA_HOME%/bin
directory, the command prompt / terminal will now prepare the Scala Interpreter ready for you to listen to your commands as follows.
C:\Users\Raghs>scala Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_80). Type in expressions to have them evaluated. Type :help for more information.
After we executed the command scala
, the Scala interpreter was invoked and has printed a Welcome message by displaying the version of Java and the Virtual Machine details.
Please remember that Scala code is executed on JVM (JRE) only. The actual code/script in Scala, will finally be executed on top of JVM , like a Java program. Hence, we could typically use the Java libraries directly in our Scala code. This is called language interoperability
2.1.2 Working with the Interpreter
Now, let us actually type the Hello, World
in the Scala Interpreter to see in action.
scala> "Hello, World" res0: String = Hello, World scala> println("Hello, World") Hello, World scala> "Hello, World" res1: String = Hello, World scala> "Hello, World".getClass().getName() res2: String = java.lang.String scala> res1 res3: String = Hello, World scala> res2 res4: String = java.lang.String
It was a very simple command we passed to the REPL Shell/Interpreter. We tried in two ways. The first one was the literal string “Hello, World” passed as double quotes surrounded String. The second command invocation to print the same Hello, World but with the println()
method.
It was considered as an expression being evaluated. Hence the interpreter printed the result with an identifier along with a prefix res0:
meaning result 0
→ the 0th index of result entries. You can see the subsequent invocations (starting from 3rd and 4th commands) have the result printed with res1:
and res2:
. The 3rd command was the same command repeated but to show that the REPL Interpreter treats every command as a separate command and prints with the next result quotient – res1:
. The 4th command is to invoke some methods on the command line. The command printed the result with res2:
. Likewise any subsequent expressions will be printed with the results alongwith the incremented index of res
.
The interesting part is the you can directly use the result names as a variable for the subsequent operations, as Scala Interpreter stores the result entries in the memory as long as the REPL Interpreter is running. You can see this in action in the last 2 invocations where in res1
and res2
were directly used like a variables and the interpreter printed the corresponding values then and there.
2.1.3 Exiting from the Interpreter
Once we are done with our work, it is always good to exit the interpreter in a normal way. To do so, you may please enter :q
to quit and exit from the Interpreter and come back to the normal Command Prompt / Terminal.
scala> :q C:\Users\Raghs\
2.2 Hello World in Scala file
As we saw earlier, the commands and expressions entered in the REPL interpreter were shortlived and once you exit from the Interpreter, you can’t get them back. If we need to work with our scripts/code any number of times in future, it is better to get the Source code saved in a file much like a Java program.
Typical to how a Java program will be saved as <fileName>.java
and we use javac <fileName>.java
to compile the source code to get a class file named <fileName>.class
and we use the Java interpreter to execute the binary file as java <fileName>
, we have the counter parts for Scala file as well.
We save the source file name as <fileName>.scala
and use scalac <fileName>.scala
to compile the source code and scala <fileName>
to execute the binary class file. We will see them in action for the same Hello World scala program below.
HelloWorld.scala
object HelloWorld { def main(args: Array[String]):Unit = { println("Hello, World"); } }
The structure is more like a Java program, where we define a main()
method that takes an array of String as an argument (which will be accepted from Command Line) and it is encapsulated inside the skeleton namedHelloWorld
. Please note that object
is a keyword in Scala that helps us to easily create a Singleton instance – meaning only one instance of a class inside a JVM.
A method in Scala is defined using the keyword def
and the parameter is declared with its type with the colon after the parameter name accompanied with the Data type. Here you see, the parameter named args
is of type Array of Strings
. The return type is specified at the end of the method declaration, which is here Unit
– one of Scala’s data types. The method definition is separated here with a =
sign with a set of curly braces {
and }
.
The only executable statement in the main method was printing the literal String “Hello, World” to console by invoking the println()
method.
Please note that the semicolon is optional for each executable statement in Scala, unlike in a Java program.
Let us now compile and execute the above scala program. It is fairly straight forward as given below.
C:\Users\Raghs> scalac HelloWorld.scala C:\Users\Raghs> scala HelloWorld Hello, World
The first command was to invoke scalac
, the Scala compiler to get our source code compiled into a .class
file. If the compilation was successful, it simply returns to the command prompt without any text being displayed on the console. The second command was to invoke scala
, the Scala Interpreter to execute the compiled class file. As per the program, it displayed Hello, World
on the console.
3. val Vs var in Scala
Let us understand the very significant and important keywords in Scala. They are val
and var
. As you might have guessed, they are the identifiers for denoting the ability to change the value of variables at a later point time in the source code/ script.
var indicates an mutable nature of the varaible’s value. That is a varaible’s value can be changed later after the inital declaration whereas val indicates an immutable nature of the variable’s value, which is like a final
keyword in Java.
var is like varying value for a variable, whereas val is like
variable + final
to restrict the subsequent changes if any to a variable in the Program.
Let us see them in action in REPL interpreter
C:\Users\Raghs> scala scala> var s = "Hello World" s: String = Hello World scala> s = "Hello Scala" s: String = Hello Scala scala> val c = "Hello, World" c: String = Hello, World scala> c = "Hello Scala" :11: error: reassignment to val c = "Hello Scala" ^ scala> c = "Hello, World" :11: error: reassignment to val c = "Hello, World" ^
As you see, in the above executions, at first we declared a variable s
of type var
. We initialized the variable s
with a String literal “Hello, World” and the REPL interpreter printed the result of the expression, which in this case is the same string literal. Later, at step 2, we reassigned the varaible s
with a different value “Hello Scala”, which was perfectly valid and legal because it was a var. Hence the second expression was allowed and printed the result, which was the latest value of s
.
However, the 3rd, 4th and 5th invocations show us a different set of results. The 3rd statement attempts to declare a variable c
of type val
, with an initial value “Hello, World”. The scala REPL interpreter printed the result of the expression, as like any other String literal in the console. However, at the 4th invocation, we attempt to reassign another value which is not allowed being the variable of type val. Hence, the REPL interpreter showed an error indicating that reassignment to val
is not permitted. It is also helpful by indicating which line and position the error had occurred with an upward arrow key in the next line indicating the position.
5th expression was to indicate that it was not just a different/new value but even the same value being assigned again will throw the same error of reassignment to a val. This was because of the fact that the variable of type val
is not allowed to have an assignment further once it is assigned with a value during its declaration.
4. Working with Strings
Scala treats a String as an array of characters. It has got several methods on its own and it allows us to use the methods from the Java API classes like String, StringBuilder etc.,
Let us play around with the Scala REPL interpreter on Strings and its methods. The following expressions (or code snippets) are self explanatory.
scala> "Hello, World".getClass.getName res0: String = java.lang.String scala> val s = "Hello, World" s: String = Hello, World scala> s.length res1: Int = 12 scala> "scala".foreach(println) s c a l a scala> "scala".drop(2) res0: String = ala scala> "scala".take(2) res1: String = sc scala> "scala".drop(2).capitalize res2: String = Ala scala> "scala".take(2).toUpperCase res3: String = SC
As you see, we have got several method on String related classes like StringLike
, StringOps
etc., in Scala Library like drop
and take
, which are useful to delete or get the characters upto the index passed. We also have methods named foreach
to ietrate each character at a time in a String, capitalize
which will make the first character of the String to be in upper case.
We could also use the String class methods from Java API – like length()
and toUpperCase
. Please note that the parantheses are optional in the REPL interpreter.
The methods can be chained – meaning the methods can be invoked one after another in a way that result of executing one method will give the return value as an input to the next method – ie., the method on the right. The last two examples show the same. The drop method leaves the 2 characters from the left (0th index) and the remaining characters are passed on to the next method on the right capitalize which converts the first character (char at 0th index) to be in upper case, which in our case is “A” (“SC” dropped from the initial input string “scala”). The same way, the toUpperCase
method was invoked on the result of invoking take(2)
on the initial input string “scala”.
You can see the API methods in StringLike class methods in Scala API. The Web page has a good set of options for filtering, searching a specific package, class, method etc.,
Let us see some String examples like String Concatenation, String Comparison, Null check etc.,
scala> val s1 = "Hello" s1: String = Hello scala> val s2 = "Hello" s2: String = Hello scala> val s3 = "H" + "ello" s3: String = Hello scala> s1 == s2 res6: Boolean = true scala> s1 == s3 res7: Boolean = true scala> val s4: String = null s4: String = null scala> s3 == s4 res8: Boolean = false scala> s1 == s4 res9: Boolean = false scala> s1.toUpperCase == s2.toUpperCase res13: Boolean = true scala> val s1: String = null s1: String = null scala> s1.toUpperCase == s2.toUpperCase java.lang.NullPointerException ... 33 elided
As you see, the first 2 expressions declare two different variables of type String
with an initial value “Hello”. The 3rd expression shows a declaration of a String variable with a String concatenation for its initial value “H” + “ello”. The 4th and 5th expressions show the String comparison where both of them are evaluated to true.
The
==
operator in Scala checks for String content equality, like theequals()
method in Java, whereas Java uses==
to check the object reference (address in memory).
An interesting thing to note that when you check for the String content equality with one of the Strings being null, Scala does NOT throw a NPE (NullPointerException) like Java. However it checks those constraints at the beginning as a safety measure and prints the result as false. However, please be careful that whenever any other attempt is made on the String contents like toUpperCase, length etc.,
, Scala obviously throws a NullPointerException
, which is what is shown in the last few code snippets above, where the toUpperCase method was invoked on a null reference S1.
5. Working with Numbers
Scala has the same set of numeric data types as that of Java. They are Char, Byte, Short, Int, Long, Float, Double, Boolean
with the same data range/limit for each of the data types. In addition, it has got its own data types like AnyRef, AnyVal, Any etc.,
. You can see the list of data types available in Scala website.
We have several methods available in the respective classes bearing the name as Data type listed above. The below code snippets / expressions are self explanatory.
scala> Int.MinValue res4: Int = -2147483648 scala> Int.MaxValue res5: Int = 2147483647 scala> Byte.MinValue res6: Byte = -128 scala> Short.MinValue res7: Short = -32768 scala> Short.MaxValue res8: Short = 32767
As you see above, the respective data type classes had the methods minValue and maxValue for getting the lower and higher boundaries for each. The expressions in the scala REPL intepreter were evaluated and printed the results for our information.
Let us have some mathematical operations on numbers in the Scala REPL interpreter.
scala> 1 + 1 res13: Int = 2 scala> "1" + "1" res14: String = 11 scala> "1".toInt + "2".toInt res15: Int = 3 scala> "1".toShort + "1".toShort res16: Int = 2 scala> "1".toByte + "1".toByte res17: Int = 2 scala> "1".toLong + "1".toLong res18: Long = 2
As you see above, the first expression was directly evaluated and the result was printed on the console. It was the sum of two numbers 1 and 1 equalling 2. However the 2nd invocation was different – where the numbers were given as String literals and hence the String Concatenation occurred producing a result of 11. If we need to parse and convert the numbers represented as a String, we can use the toInt
method for the same. We have similar methods to convert to the different other data types like toByte, toLong, toShort
etc., which you see in the last few expressions. These toInt() etc., methods convert the string literal into the corresponding numeric form and apply the mathematical operation to produce the result.
Let us see some negative scenarios where you may get an error while attempting to convert the String literal to a numeric form.
scala> "129".toByte java.lang.NumberFormatException: Value out of range. Value:"129" Radix:10 at java.lang.Byte.parseByte(Byte.java:150) at java.lang.Byte.parseByte(Byte.java:174) at scala.collection.immutable.StringLike$class.toByte(StringLike.scala:264) at scala.collection.immutable.StringOps.toByte(StringOps.scala:30) ... 33 elided scala> "foo".toInt java.lang.NumberFormatException: For input string: "foo" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:492) at java.lang.Integer.parseInt(Integer.java:527) at scala.collection.immutable.StringLike$class.toInt(StringLike.scala:272) at scala.collection.immutable.StringOps.toInt(StringOps.scala:30) ... 33 elided
The first expression was attempting to convert the String Literal 129 to a Byte. However it failed because the Byte value range was only from -128 to 127. Hence you got an error with a meaningful description (see the very first line in the stack trace), which helps us to understand the mistake and take a corrective action. The second expression was obvious where a non-numeric value (actual String value) was attempted to be converted an Integer, which will definitely throw a NumberFormatException
.
You can see that the methods toInt, toByte
are present in the StringOps
class which then further delegated to the toInt()
method of the class StringLike
. These calls are further stacked up with the Java API method parseInt(), parseByte()
of the respective Wrapper classes Integer, Byte
.
Let us see some arithmetic operations with REPL interpreter.
scala> var count = 1 count: Int = 1 scala> count ++ :12: error: value ++ is not a member of Int count ++ ^ scala> count += 1 scala> count res27: Int = 2 scala> count = count + 1 count: Int = 3
As you see, the first expression declared a variable of type var
count with an initial value of 1. To increment the value with 1, we use the ++
in Java. However in Scala, it is slightly different as it uses +=
in place. The 2nd expression fails due to the usage of ++
whereas the 3rd expression gets it right. However the evaluation of expression did not yield any result in the console. The 4th expression printed the value of count
which is now 2 after the increment operation. The 5th expression shows the usual way to add 1 to the value of a variable. Here the value is explicitly assigned back to the variable, and hence the result (3) is printed on the console.
Please note that the symbols
+, -, *, /
etc., are the methods in Scala and NOT the operators like in Java.
Because there is no method named +=
in Int class, we got an error on 2nd expression above.
Let us see how easy to work with a range of numbers in Scala.
scala> val r = 1 to 10 r: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> var r = 1 to 10 by 2 r: scala.collection.immutable.Range = Range(1, 3, 5, 7, 9) scala> for(i <- 1 to 5) println(i) 1 2 3 4 5 scala> for(i for(i <- 1 until 5) println(i) 1 2 3 4
The first expression above used the construct 1 to 10
to have a range of numbers from 1 to 10. The result shows that the a Range
of type scala.collection.immutable.Range.Inclusive
was created and assigned to the variable r
.
The 2nd expression shows that we can create a range of numbers from 1 to 10 with an incremental value of 2. That is why the resultant Range has the numbers 1, 3, 5, 7 and 9.
.
The 3rd expression uses a for loop with a range within the paranthesis indicating that 1 to 5 to be used, with a closure that prints each of the value in the range in a separate line.
The 4th expression uses a for loop but with the until
which is upto the max value, meaning one lesser than the max boundary. The result printed on the console ranges from 1 to 4 and NOT upto 5.
6. Control Structures in Scala
Like many other high level Programming languages, Scala offers if, if-else, switch, while, for
control structures as a control statements and looping statements. We will see the examples for few of them below.
If statement has an expression and if that expression evalutes to true, the statement will be executed.
scala> var num = 2 num: Int = 2 scala> if(num%2==0) println("Even") Even scala> if(num%2!=0) println("Odd")
The first expression above assigns the value 2 to a variable named num
. The 2nd expression tests for the value of the variable ‘num’ being even and if so, it prints the String “Even” in the console. Since the variable ‘num’ holds the value ‘2’, the condition in the if statement evaluates to true and hence the String “Even” is printed on the console as a result.
If you see the 3rd expression, the if statement checks for the value of the variable ‘num’ for odd number. Since the value 2 is not an odd number, the condition fails but nothing gets printed because the if statement will execute ONLY when the condition evaluates to true.
If-else – helps in cirumstances when we want to handle an alternate situation when the condition inside the if statement does not evaluate to true. See the previous example, it would be good if we have something else printed when the condition not evaluates to true, which otherwise be a return nothing on the console.
scala> if(num%2!=0) println("Odd") else println("Even") Even scala> num=1 num: Int = 1 scala> if(num%2!=0) println("Odd") else println("Even") Odd
As you see, the if statement was used with an else
to have a different message printed on the alternate. The above examples show the same in action after altering the value of the variable ‘num’ to 1.
scala> val x=10; val y =20 x: Int = 10 y: Int = 20 scala> val max = if(x>y) x else y max: Int = 20
The first expression above declares two variables x and y in the same line with the values 10 and 20 respectively. The 2nd expression uses an if-else statment to check for the bigger value held by x and y and the chosen value is assigned to the meaningful variable named ‘max’.
for – loop is useful when you have a fixed boundaried collection to operate. It is used in two flavours – simple for loop and a variant foreach loop to iteration through a collection.
scala> for(i <- 1 to 10) println(i) 1 2 3 4 5 6 7 8 9 10 scala> "hello".foreach(println) h e l l o
The above expressions show that usage of for, foreach
loops in a straightforward manner.
for with an iterator guard – is a special case in Scala where a for loop can have a conditional statement to give the eligibility of the element to be considered further. It acts like a filter to each element in the collection being operated.
Sytax of an Iterator Guard is :
for(<identifier> <- <collection/range> if <Boolean expression>) { ... }
scala> for(i <- 1 to 10 if(i%2==0)) println(i) 2 4 6 8 10
The above expression used a for loop with an iterator guard to filter out ONLY the even numbers. The element will get printed ONLY if it is passing out of the filter, which is i%2==0
.
while – loop is used at a situation when you are not sure of the boundary of the collection especially when to stop iterating.
7. Collections in Scala
Scala offers several different Collection elements like List, Set, and Map
. We will see the list collection with an example below.
We can instantiate a List by calling it as a function and passing the list of elements as a comma separated values within the paranthesis.
scala> val numbers=List(1,2,3,4,5) numbers: List[Int] = List(1, 2, 3, 4, 5) scala> numbers.size res55: Int = 5
The above expressions create a List with the numbers from 1 to 5 and the size of which is printed. Let us see how easily we can iterate the collections using a for loop and its variants.
scala> numbers.foreach(println) 1 2 3 4 5 scala> for(n for(n <- numbers if(n%2==0)) println(n) 2 4
The 1st expression used a foreach loop as a method invoked on the collection to print out each element in the collection, whereas the 2nd expression used the for loop on the collection with a loop variable named n
to hold each value at a time from the collection and prints out the same. The 3rd expression uses the for loop with an iterator guard
to print out ONLY the even numbers.
Let us see few of the interesting methods available in Scala API for List objects. head method gets you the very first element – at 0th index, tail method invokes the rest of the elements in the collection excluding the very first at 0th index.
scala> numbers.head res60: Int = 1 scala> numbers.tail res61: List[Int] = List(2, 3, 4, 5) scala> numbers(0) res67: Int = 1 scala> numbers(2) res68: Int = 3 scala> numbers.tail.size res69: Int = 4 scala> numbers.tail(0) res62: Int = 2 scala> numbers.tail(2) res63: Int = 4
The above code snippets and expressions are self explanatory. The first element at index 0 is retrieved by using head
method and the rest of the elements in the collection excluding the 0th element is retrieved by using the tail
method. A particular element from the collection is obtained directly by passing its index as an argument like numbers(0)
etc.,
Using method chaining, the res69
was obtained of the size after tail() method was applied. Initial list was containing 5 elements, whereas the tail() method gives you the list of 4 elements (from element index 1 to the end, excluding the element at index 0). The size of which was 4.
The last 2 expressions were attempting to retrieve a particular element of the resultant list of tail() method. The tail(0)
will get the element at 0th index after tail() method – which is 2 in the list (2,3,4,5)
, whereas tail(2)
will get the element at index 2 of the list 2,3,4,5
which is 4. Remember all elements in a collection starts from Index 0.
Let us look at another useful method isEmpty on a collection which returns true or false depending on the elements available in a collection.
scala> numbers.isEmpty res64: Boolean = false scala> numbers.tail.tail.size res70: Int = 3 scala> numbers.tail.tail.tail.tail.tail.size res71: Int = 0 scala> numbers.tail.tail.tail.tail.tail.isEmpty res72: Boolean = true
The first expression invoked isEmpty
on the collection numbers
, which returns false
as the underlying collection has a list of values/elements from 1 to 5. The 2nd expression showed the method chaining of size() method invoked after two successive invocations of tail
method on the collection numbers
. The result of whcih is 3.
The 3rd expression applied 5 consecutive tail() methods on the numbers
which eventually empties the collection and hence the size() method at the last returns 0. Similarly, the 4th expression invokes the isEmpty
method with the same method chaining of 5 consecutive tail() methods, which in case returns true
.
You need to be careful while iterating the elements. For example, the below code snippet throws an UnsupportedOperationException
when the tail method was invoked on an empty list – due to the consecutive method chanining. Please use them sparingly as they are here shown for the demonstration purpose.
scala> numbers.tail.tail.tail.tail.tail.tail.size java.lang.UnsupportedOperationException: tail of empty list at scala.collection.immutable.Nil$.tail(List.scala:422) at scala.collection.immutable.Nil$.tail(List.scala:417) ... 33 elided
8. Conclusion
Hope you had enjoyed the Beginner Tutorial of Scala and you got a good taste of it. Please try the examples on your own by exploring the different methods available in the Scala API. You would really enjoy the power of Scala, especially if are coming from a professional Java development background as Scala offers a more consistent and simple way of doing things which is more verbose in Java.
9. References
You may please refer the following URLs for further reading.
- Scala – Wikipedia
- Critism of Java – Wikipedia
- Download Scala
- Scala Official Tutorial – Tour of Scala
- Scala Datatypes
- Scala Language API Documentation
- Getting Started with Scala
10. Download the Source Code
This is a beginner’s tutorial to Scala having all the examples tested in the Command Prompt / Shell against Scala Version 2.11.7.
The zip file has only the source code of HelloWorld.scala
where the rest of the examples were executed in REPL Interpreter
.
You can download the full source code of this example here: Scala Tutorial for Beginners.