Introduction Data Science Programming Handout Set 1A
Introduction Data Science Programming Handout Set 1A
the de facto language for the current Big Data tools like Apache Spark, Finagle,
Scalding, etc.
Many of the high performance data science frameworks that are built on top of Hadoop usually are
written and use Scala or Java. The reason Scala is used in these environments is because of its amazing
concurrency support, which is key in parallelizing a lot of the processing needed for large data sets. It
also runs on the JVM, which makes it almost a no-brainer when paired with Hadoop.
Also with the industry adoption of Apache Spark, ( which is leading Scala framework for cloud
computing and Big Data) Scala has quickly become popular among Big Data professionals. If you are
going for an interview for any of the Big Data job openings that require Apache Spark experience then
you should prepare for Scala interview questions as well because Spark is written in Scala.
Prerequisites
• Scala Programming is based on Java, so if you are aware of Java syntax, then it's pretty easy to
learn Scala.
• Further if you do not have expertise in Java but if you know any other programming language
like C, C++ or Python then it will also help in grasping Scala concepts very quickly.
• It is also very important that you have done CMT 203: Introduction to system Administration.
3
Indeed almost all big data analysis tools and concepts are largely based on open source
solutions than proprietary solutions.
Features of Scala
Object-oriented Programming Language
Scala is a pure object-oriented language in the sense that every value is an object. Types and behavior
of objects are described by classes and traits -to be discussed later.
Classes are extended by subclassing and a flexible mixin-based composition mechanism as a clean
replacement for multiple inheritance.
Scala is an object-oriented language in pure form: every value is an object and every operation is a
method call.
Example, 1 + 2 in Scala, means you are actually invoking a method named + defined in class Int . You
can define methods with operator-like names that clients of your API can then use in operator notation.
This generalization of functions provides great expressiveness, which often leads to very legible and
concise programs. It also plays an important role for scalability.
• The second main idea of functional programming is that the operations of a program should
map input values to output values rather than change data in place.
Example Illustration
Consider the implementation of strings in Ruby and in Java.
In Ruby, a string is an array of characters. Characters in a string can be changed individually. For
instance you can change a semicolon character in a string to a period inside the same string object.
In Java and Scala, on the other hand, a string is a sequence of characters in the mathematical sense.
Replacing a character in a string using an expression like s.replace(';', '.') yields a new string object,
which is different from s .
We say that strings are immutable ( Cannot be changed in place) in Java whereas they are mutable in
Ruby.
Functional programming main principle is that methods should not have any side effects. They should
communicate with their environment only by taking arguments and returning results.
Methods like replace are called referentially transparent, which means that for any given input the
method call could be replaced by its result without affecting the program’s semantics.
• Immutable data structures are one of the cornerstones of functional programming.
The Scala libraries define many more immutable data types on top of those found in the Java APIs.
For instance, Scala has immutable lists, tuples, maps, and sets.
In addition to Immutable data structures Functional languages encourage also referentially
transparent methods.
• The Scala compiler compiles your Scala code into Java Byte Code, which can then be executed
by the 'scala' command. The 'scala' command is similar to the java command, in that it
executes your compiled Scala code.
• The combination of both styles in Scala makes it possible to express new kinds of programming
patterns and component abstractions.
• Scala has a set of convenient constructs that help you get started quickly and let you program in
a pleasantly concise style. At the same time, you have the assurance that you will not outgrow
the language.
• You can always tailor the program to your requirements, because everything is based on library
modules that you can select and adapt as needed.
Scala vs Java
Scala has a set of features that completely differ from Java. Some of these are −
• All types are objects
• Type inference
6
• Nested Functions
• Functions are objects
• Domain specific language (DSL) support
• Traits
• Closures
• Concurrency support inspired by Erlang
Scala is Concise
Scala programs tend to be short and less noisy as compared to java programming. Scala programmers
have reported reductions in number of lines of up to a factor of ten compared to Java. A more
conservative estimate would be that a typical Scala program should have about half the number of lines
of the same
program written in Java. Fewer lines of code means:
• Less typing,
• Also less effort at reading and understanding programs
• Fewer possibilities of errors all resulting to
• Shorter system development
Example Illustration
Compare the example below that shows how you write classes and constructors in Java and
Scala.
class MyClass {
private int index; class MyClass(index: Int, name: String)
private String name;
public MyClass(int index, String name) { Explanation
this.index = index; The Scala compiler will produce a class that has
this.name = name; two private instance variables, an Int named index
}
and a String named name , and a constructor that
}
takes initial values for those variables as
parameters.
The code of this constructor will initialize the two
instance variables with the values passed as
parameters.
7
Scala is high-level
Programmers are constantly grappling with complexity. To program productively, you must understand
the code on which you are working.
Overly complex code has been the downfall of many a software project and unfortunately in some
cases we can’t avoid complex requirements while writing software. It must instead be managed.
Scala helps you manage complexity by letting you raise the level of abstraction in the interfaces you
design and use.
Example Illustration
As an example, imagine you have a String variable name , and you want to find out whether or not that
String contains an upper case character. In Java, you might write this:
nameHasUpperCase = true;
break;
Explanation
The Java code treats strings as low-level entities that are stepped through character by character in a
loop. The Scala code treats the same strings as higher-level sequences of characters that can be queried
with predicates.
Clearly the Scala code is much shorter and easier to understand than the Java code. So the Scala code
weighs less heavily on the total complexity cost. It also minimises opportunity to make errors.
The predicate _.isUpperCase is an example of a function literal in Scala. It describes a function that
takes a character argument (represented by the underscore character), and tests whether it is an upper
case letter
8
We assume that the readers of this tutorial have Java SDK version 1.8.0_31 installed on their system.
In case you do not have Java SDK, download its current version from
http://www.oracle.com/technetwork/java/javase/downloads/index.html and install it.
Append the full path of Java compiler location to the System Path.
Execute the command java -version from the command prompt as explained above.
[ Starting to unpack ]
[ Unpacking finished ]
Finally, open a new command prompt and type Scala -version and press Enter. You should see the
following −
Interactive Mode
Open the command prompt and use the following command to open Scala.
\>scala
Type the following text to the right of the Scala prompt and press the Enter key −
scala> println("Hello, Scala!");
object HelloWorld {
/* This is my first scala program.
* This will print 'Hello World' as the output
*/
def main(args: Array[String]) {
println("Hello, world!") // prints Hello World
}
}
Once you are finished you have created a file HelloWorld.scala. in Desktop/Scala .
Note: You can use any of you favorite editor to create files. Popular choices include nano, vim, gedit ,
etc.
Use the ‘scalac’ command is used to compile the Scala program. It will generate a few class files in the
current directory. One of them will be called HelloWorld.class which is bytecode which will run on
Java Virtual Machine (JVM) using ‘scala’ command.
Output
Hello, World! It automatically generated or user-defined name to refer to
the computed value ( res0 means result 0),
A bit of Scala Simple Tasks . • a colon ( : ), followed by the type of the expression ( Int ),
• an equals sign ( = ), and
\> 4 + 3 • the value resulting from evaluating the expression ( 7).
res0: Int = 7
The resX identifier may be used in later lines. For instance, since res0 was set to 7 previously, then res0
* 3 will be 21:
\> res0*3
res1: Int = 21
14
The type Int names the class Int in the package scala . Packages in Scala are similar to packages in
Java: they partition the global namespace and provide a mechanism for information hiding.
Values of Scala class Int correspond to Java’s int values.
Note:
1. All of Java’s primitive types have corresponding classes in the scala package. For example,
scala.Boolean corresponds to Java’s boolean, scala.Float corresponds to Java’s float.
2. And when you compile your Scala code to Java bytecodes, the Scala compiler will use Java’s
primitive types where possible to give you the performance benefits of the primitive types.
To exit the interpreter, you can do so by entering :quit or :q .
scala> :quit
Scala Identifiers
All Scala components require names. Names are used for objects, classes, variables and methods are
are referred to as called identifiers.
A keyword cannot be used as an identifier and identifiers are case-sensitive. Scala supports four types
of identifiers.
Alphanumeric Identifiers
An alphanumeric identifier starts with a letter or an underscore, which can be followed by further
letters, digits, or underscores. The '$' character is a reserved keyword in Scala and should not be used in
identifiers.
Following are legal alphanumeric identifiers − age, salary, _value, __1_value
Following are illegal identifiers − $salary, 123abc, -salary
Operator Identifiers
An operator identifier consists of one or more operator characters. Operator characters are printable
ASCII characters such as +, :, ?, ~ or #.
Following are legal operator identifiers − + ++ ::: <?> :>
The Scala compiler will internally "mangle" operator identifiers to turn them into legal Java identifiers
with embedded $ characters. For instance, the identifier :-> would be represented internally as
$colon$minus$greater.
Mixed Identifiers
A mixed identifier consists of an alphanumeric identifier, which is followed by an underscore and an
operator identifier.
Following are legal mixed identifiers − unary_+, myvar_=
Here, unary_+ used as a method name defines a unary + operator and myvar_= used as method name
defines an assignment operator (operator overloading).
16
Literal Identifiers
A literal identifier is an arbitrary string enclosed in back ticks (` . . . `).
Following are legal literal identifiers − `x` `<clinit>` `yield`
17
Scala Keywords
The following list shows the reserved words in Scala. These reserved words may not be used as
constant or variable or any other identifier names.
Comments in Scala
Scala supports single-line and multi-line comments very similar to Java. Multi-line comments may be
nested, but are required to be properly nested. All characters available inside any comment are ignored
by Scala compiler.
object HelloWorld {
/* This is my first java program.
* This will print 'Hello World' as the output
* This is an example of multi-line comments.
*/
def main(args: Array[String]) {
// Prints Hello World
// This is also an example of single line comment.
println("Hello, world!")
}
}
Newline Characters
• Scala is a line-oriented language where statements may be terminated by semicolons (;) or
newlines. A semicolon at the end of a statement is usually optional.
• You can type one if you want but you don't have to if the statement appears by itself on a single
line.
18
• On the other hand, a semicolon is required if you write multiple statements on a single line.
• The code below is an example of multiple statements usage.
val s = "hello"; println(s)
Scala Packages
A package is a named module of code. A package can also be described as a collection of related
objects.
Scala packages can be imported so that they can be referenced in the current compilation scope. The
following statement imports the contents of the scala.xml package −
import scala.xml._
You can import a single class and object, for example, HashMap from the scala.collection.mutable
package −
import scala.collection.mutable.HashMap
You can import more than one class or object from a single package, for example, TreeMap and
TreeSet from the scala.collection.immutable package −
import scala.collection.immutable.{TreeMap, TreeSet}
All the data types listed above are objects. There are no primitive types like in Java.
This means that you can call methods on an Int, Long, etc.
Integral Literals
Integer literals are usually of type Int, or of type Long when followed by a L or l suffix. Here are some
integer literals − 0,035, 21, 0xFFFFFFFF, 0777L
Boolean Literals
The Boolean literals true and false are members of type Boolean.
Symbol Literals
A symbol literal 'x is a shorthand for the expression scala.Symbol("x"). Symbol is a case class, which
is defined as follows.
20
package scala
final case class Symbol private (name: String) {
override def toString: String = "'" + name
}
Character Literals
A character literal is a single character enclosed in quotes. The character is either a printable Unicode
character or is described by an escape sequence. Here are some character literals −
'a' , '\u0041', '\n' ,'\t'
String Literals
A string literal is a sequence of characters in double quotes. The characters are either printable Unicode
character or are described by escape sequences. Here are some string literals −
"Hello,\nWorld!"
"This string contains a \" character."
Multi-Line Strings
A multi-line string literal is a sequence of characters enclosed in triple quotes """ ... """. The
sequence of characters is arbitrary, except that it may contain three or more consecutive quote
characters only at the very end.
Characters must not necessarily be printable; newlines or other control characters are also permitted.
Here is a multi-line string literal −
"""the present string
spans three
lines."""
Null Values
The null value is of type scala.Null and is thus compatible with every reference type. It denotes a
reference value which refers to a special "null" object.
Escape Sequences
The following escape sequences are recognized in character and string literals.
Example
object Test {
def main(args: Array[String]) {
println("Hello\tWorld\n\n" );
}
}
When the above code is compiled and executed, it produces the following result −
Output
Hello World
22
Scala - Variables
Variables are reserved memory locations to store values. This means that when you create a variable,
you reserve some space in memory.
Based on the data type of a variable, the compiler allocates memory and decides what can be stored in
the reserved memory.
These means you can store integers, decimals, or characters in variables.
Variable Declaration
Scala has two kinds of variables, val s and var s. A val variable is similar to a final variable in Java.
Once initialized, a val can never be reassigned. A var variable, by contrast, is similar to a non-final
variable in Java. A var can be reassigned throughout its lifetime.
Example1: Using val
scala> val msg = "Hello, world!"
The type of msg is java.lang.String . This is because Scala strings are implemented by Java’s String
class and in this case it is immutable.
NOTE:
You notice in the example above that we did not specify that the variable should be of type
java.lang.String yet Scala returned a java.lang.String.
This example illustrates type inference, Scala’s ability to infer the correct type. This is made possible
because you initialized msg with a string literal.
Example 2: Using var
var myVar : String = "Foo"
Here, myVar is declared using the keyword var. It is a variable that can change value. It is an example
of a mutable variable.
Syntax
val or val VariableName : DataType = [Initial Value]
23
If you do not assign any initial value to a variable, then it is valid as follows −
Syntax
var myVar :Int;
val myVal :String;
val b: Byte = 1
val x: Int = 1
val l: Long = 1
val s: Short = 1
val d: Double = 2.0
val f: Float = 3.0
In the first four examples, if you don’t explicitly specify a type, the number 1 will default to an Int, so
if you want one of the other data types — Byte, Long, or Short — you need to explicitly declare
those types.
Numbers with a decimal (like 2.0) will default to a Double, so if you want a Float you need to
declare a Float, as shown in the last example.
Because Int and Double are the default numeric types, you typically create them without explicitly
declaring the data type:
val i = 123 // defaults to Int
val x = 1.0 // defaults to Double
The REPL shows that those examples default to Int and Double:
scala> val i = 123
i: Int = 123
A great thing about BigInt and BigDecimal is that they support all the operators you’re used to
using with numeric types:
scala> var b = BigInt(1234567890)
24
b: scala.math.BigInt = 1234567890
scala> b + b
res0: scala.math.BigInt = 2469135780
scala> b * b
res1: scala.math.BigInt = 1524157875019052100
scala> b += 1
scala> println(b)
1234567891
Though once again, you can use the explicit form, if you prefer:
val name: String = "Bill"
val c: Char = 'a'
you can append them together like this, if you want to:
val name = firstName + " " + mi + " " + lastName //Java like
This form creates a very readable way to print strings that contain variables:
println(s"Name: $firstName $mi $lastName")
As shown, all you have to do is to precede the string with the letter s, and then put a $ symbol before
your variable names inside the string. This feature is known as string interpolation.
String interpolation in Scala provides many more features. For example, you can also enclose your
25
For some people that’s easier to read, but an even more important benefit is that you can put
expressions inside the braces, as shown in this REPL example:
scala> println(s"1+1 = ${1+1}")
1+1 = 2
• The raw interpolator performs no escaping of literals (such as \n) within the string
• You can create your own string interpolators
Multiline strings
A second great feature of Scala strings is that you can create multiline strings by including the string
inside three double-quotes:
val speech = """Four score and
seven years ago
our fathers ..."""
That’s very helpful for when you need to work with multiline strings. One drawback of this basic
approach is that lines after the first line are indented, as you can see in the REPL:
scala> val speech = """Four score and
| seven years ago
| our fathers ..."""
speech: String =
Four score and
seven years ago
our fathers ...
A simple way to fix this problem is to put a | symbol in front of all lines after the first line, and call the
stripMargin method after the string:
val speech = """Four score and
|seven years ago
|our fathers ...""".stripMargin
The REPL shows that when you do this, all of the lines are left-justified:
scala> val speech = """Four score and
| |seven years ago
| |our fathers ...""".stripMargin
speech: String =
Four score and
26
Because this is what you generally want, this is a common way to create multiline strings.
}
Then compile it with scalac: $ scalac HelloInteractive.scala
27
As you saw in this application, you bring classes and methods into scope in Scala just like you do with
Java and other languages, with import statements.
import scala.io.StdIn.readLine
That import statement brings the readLine method into the current scope so you can use it in the
application.
default input), specified by a format specifier, returning only the first three values extracted,
according to the format specification.
}
1.0 Save the code as KeyBoardInputs.scala ,Compile it and run
N.b The code on running only calls the totalMarks1(). To run totlaMarks() modify the
code accordingly
Multiple Assignments
Scala supports multiple assignments. If a code block or method returns a Tuple (Tuple − Holds
collection of Objects of different types), the Tuple can be assigned to a val variable.
Syntax
val (myVar1: Int, myVar2: String) = Pair(40, "Welcome")// Pair is a tuple
Syntax
val (myVar1, myVar2) = Pair(40, "Welcome")
29
Variable Scope
Variables in Scala can have three different scopes depending on the location where they are being used.
They can be fields, method parameters and local variables. We discuss these concepts below
Fields
Fields are variables that belong to an object. The fields are accessible from inside every method in the
object. ( Remember fields in Java)
Fields can also be accessible outside the object depending on what access modifiers the fields is
declared with. Object fields can be both mutable and immutable types and can be defined using either
var or val.
Method Parameters
Method parameters are variables, which are used to pass the value inside a method, when the method is
called.
Method parameters are only accessible from inside the method but the objects passed in may be
accessible from the outside, if you have a reference to the object from outside the method.
Method parameters are always immutable which means they are all defined by val keyword.
Local Variables
Local variables are variables declared inside a method. Local variables are only accessible from inside
the method, but the objects you create may escape the method if you return them from the method.
Local variables can be both mutable and immutable types and can be defined using either var or val.
30
Scala - Operators
An operator is a symbol that tells the compiler to perform specific mathematical or logical
manipulations. Scala is rich in built-in operators and provides the following types of operators −
• Arithmetic Operators
• Relational Operators
• Logical Operators
• Bitwise Operators
• Assignment Operators
Arithmetic Operators
The following arithmetic operators are supported . Assume variable A holds 10 and variable B holds 20,
then −
Relational Operators
The following relational operators are supported
Logical Operators
The following logical operators are supported by Scala language. For example, assume variable A holds
1 and variable B holds 0, then −
Bitwise Operators
Bitwise operator works on bits and perform bit by bit operation.
The truth tables for &, |, and ^ are as follows −
The Bitwise operators supported by Scala language is listed in the following table. Assume variable A
holds 60 and variable B holds 13, then −
Assignment Operators
There are following assignment operators supported by Scala language −
Op Description Example
Simple assignment operator, Assigns values from right side C = A + B will assign value of A
=
operands to left side operand + B into C
Add AND assignment operator, It adds right operand to the left
+= C += A Means C = C + A
operand and assign the result to left operand
Subtract AND assignment operator, It subtracts right operand
-= C -= A Means C = C - A
from the left operand and assign the result to left operand
Multiply AND assignment operator, It multiplies right operand
*= C *= A Means C = C * A
with the left operand and assign the result to left operand
Divide AND assignment operator, It divides left operand with
/= C /= A Means C = C / A
the right operand and assign the result to left operand
Modulus AND assignment operator, It takes modulus using two
%= C %= A Means C = C % A
operands and assign the result to left operand
<<= Left shift AND assignment operator C <<= 2 is same as C = C << 2
>>= Right shift AND assignment operator C >>= 2 is same as C = C >> 2
&= Bitwise AND assignment operator C &= 2 is same as C = C & 2
^= bitwise exclusive OR and assignment operator C ^= 2 is same as C = C ^ 2
|= bitwise inclusive OR and assignment operator C |= 2 is same as C = C | 2
For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence
than +, so it first gets multiplied with 3*2 and then adds into 7.
Take a look at the following table. Operators with the highest precedence appear at the top of the table
and those with the lowest precedence appear at the bottom. Within an expression, higher precedence
operators will be evaluated first.
Introduction To functions
Functions are a key concepts to any programming and scripting language. Here we introduce simple
functions in Scala:
Function Definition Function definitions start with def .
The function’s name, in this case max , is
scala> def max(x: Int, y: Int): Int = { followed by a comma-separated list of
if (x > y) x
else y parameters in parentheses.
} The function’s result type is an equals sign
max: (Int,Int)Int and pair of curly braces that contain the body
NOTE: of the function.
• A type annotation must follow every function parameter, preceded by a colon, because the
Scala compiler (and interpreter) does not infer function parameter types unlike in other use
of variables..
• After the close parenthesis of max ’s parameter list you’ll find another “ : Int ” type annotation.
This one defines the result type of the max function itself. Sometimes the Scala compiler will
require you to specify the result type of a function.
• If the function is recursive, 7 for example, you must explicitly specify the function’s result type.
• In the above case however, you may leave the result type off and the compiler will infer it.
• Also, if a function consists of just one statement, you can optionally leave off the curly braces.
Thus, you could alternatively write the max function like this:
scala> def max2(x: Int, y: Int) = if (x > y) x else y
max2: (Int,Int)Int
• Following the function’s result type is an equals sign and pair of curly braces that contain the
body of the function.
• The equals sign that precedes the body of a function hints that in the functional world view, a
function defines an expression that results in a value.
35
| println("Hello Hello")
| }
The same method, with the method’s return type explicitly shown:
def add(a: Int, b: Int): Int = a + b
Multiline Example
scala> def addThenDouble(a: Int, b: Int): Int = {
val sum = a + b
val doubled = sum * 2
doubled
}
scala> addThenDouble(4,5)
mean?
• “ greet ” is, the name of the function.
• The empty parentheses ind icate the function takes no parameters.
• The Unit is greet ’sresult type. A result type of Unit indicates the function returns no value
Scala’s Unit type is similar to Java’s void type, and in fact every void -returning method in Java is
mapped to a Unit -returning method in Scala.
Methods with the result type of Unit , therefore, are only executed for their side effects. In the case of
greet() , the side effect is a friendly greeting printed to the standard output.
3. Functions Call-by-Name
Normally parameters to functions are by-value parameters; that is, the value of the parameter is
determined before it is passed to the function.
But what if we need to write a function that accepts as a parameter an expression that we don't want
evaluated until it's called within our function? For this circumstance, Scala offers call-by-name
parameters.
A call-by-name mechanism passes a code block to the call and each time the call accesses the
parameter, the code block is evaluated and the value is calculated. Here, delayed prints a message
demonstrating that the method has been entered. Next, delayed prints a message with its value. Finally,
delayed prints ‘t’.
The following program shows how to implement call–by–name.
Example
4. object Example {
5. def main(args: Array[String])={
6. delayed(time());
7. }
8.
9. def time() = {
10. println("Getting time in nano seconds")
11. System.nanoTime
12. }
13. def delayed( t: => Long ) = {
14. println(“System now:”+System.nanoTime);
15. println("In delayed method")
16. println("Time Parameter now: " + t)
17. }
18. }
37
Output
In delayed method
Getting time in nano seconds
Param: 2027245119786400
Example
object StringExample {
def main(args: Array[String]) {
printStrings("Hello", "Scala", "Python");
}
//A function definition that specifies that the String can be repeated
// The function can be called with any number of string objects
def printStrings( args:String* )= {
var i : Int = 0;
for( arg <- args ){
println("Arg value[" + i + "] = " + arg );
i = i + 1;
}
}
}
Output
Arg value[0] = Hello
Arg value[1] = Scala
Arg value[2] = Python
Example
object NamedExample {
def main(args: Array[String]) {
//The function is called in any order
printInt(b = 5, a = 7);
}
Output
Value of a : 7
Value of b : 5
Example
object DefaultExample {
def main(args: Array[String]) {
//The function is called without specifying the arguments
println( "Returned Value : " + addInt() );
}
def addInt( a:Int = 5, b:Int = 7 ) : Int = {
var sum:Int = 0
sum = a + b
return sum
}
39
}
Output
Returned Value : 12
When working with default arguments make sure that any default arguments
must be after all non-default arguments.
| println(s"$a $b")
|}
func: (a: Int, b: String)Unit
scala> func("Ayushi")
<console>:13: error: not enough arguments for method func: (a: Int, b: String)Unit.
Unspecified value parameter b.
func("Ayushi")
^
7. Recursion Functions
Recursion plays a big role in pure functional programming and Scala supports recursion functions very
well. Recursion means a function that call itself repeatedly.
Example: Factorial
object RecursiveExample {
def main(args: Array[String]) {
for (i <- 1 to 10)
println( "Factorial of " + i + ": = " + factorial(i) )
}
Output
Factorial of 1: = 1
Factorial of 2: = 2
Factorial of 3: = 6
Factorial of 4: = 24
Factorial of 5: = 120
Factorial of 6: = 720
Factorial of 7: = 5040
Factorial of 8: = 40320
Factorial of 9: = 362880
Factorial of 10: = 3628800
Example
object NestedExample {
def main(args: Array[String])= {
printResults(45,25,30,50,23,60,76,49,52);
}
// Can accept a variable arguments array
def printResults( args:Int* ) = {
var i : Int = 0;
for( mark <- args ){
println("Mark value[" + i + "] = " + mark+ "Grade= "+grade(arg) );
i = i + 1;
}
// A nested function to return the grade for a given marks
def grade(mark:Int): String={
if( mark >= 70 )"A" else if( mark >= 60 )"B" else if( mark >= 50 )"C"
else if( mark >= 40 )"D" else "F"
}//End of grade
}//End of printResults
}
41
Output
Arg value[0] = 1 Grade=F
Arg value[1] = 20 Grade=F
Arg value[2] = 30 Grade=F
Arg value[3] = 50 Grade=C
Arg value[4] = 23 Grade=F
Arg value[5] = 60 Grade=B
Example
Let us examine the code below
import java.util.Date
object PartFunExample {
def main(args: Array[String]) {
val date = new Date //Creating a date object
log(date, "message1" )
Thread.sleep(1000)
log(date, "message3" )
}
//A function that recieves a message and the date and logs the msg
def log(date: Date, message: String) = {
println(date + "----" + message)
}
}
42
Output
Mon Dec 02 12:52:41 CST 2013----message1
Mon Dec 02 12:52:41 CST 2013----message2
Mon Dec 02 12:52:41 CST 2013----message3
Here, the log( ) method takes two parameters: date and message.
We want to invoke the method multiple times, with the same value for date but different values for
message.
The goal is to eliminate the noise of passing the date to each call by partially applying that argument
to the log( ) method.
This can be achieved by binding a value to the date parameter and leave the second parameter
unbound by putting an underscore at its place.
The result is a partially applied function that we've stored in a variable.
Example
import java.util.Date
object AppliedDemo {
def main(args: Array[String]) {
val date = new Date
// Note the magic of the underscore
val logWithDateBound = log(date, _ : String)
// First call to the function
logWithDateBound("message1" )
Thread.sleep(1000)
// Second call to the function
logWithDateBound("message2" )
Thread.sleep(1000)
// Third call to the function
logWithDateBound("message3" )
}
Output
Mon Dec 02 12:53:56 CST 2013----message1
Mon Dec 02 12:53:56 CST 2013----message2
Mon Dec 02 12:53:56 CST 2013----message3
43
Example
1. object HOFExample {
2. def main(args: Array[String]) {
3. println( apply( layout, 10) )
4. }
5.
6. def apply(f: Int => String, v: Int) = f(v)
7.
8. def layout[A](x: A) = "[" + x.toString() + "]"
9. }
Output
[10]
This is a scala generic function (Parameterized ) that can take any type parameter.
In this case , it can take an Int, a Float , a String etc. So long as the type suport the toString() method.
44
Consider a case of an application that can be used to to draw a random element from a
list of element.
In such a case we make use of generic function as show below.
With this change, the method can now be called on a variety of types:
randomElement(Seq("Aleka", "Christina", "Tyler", "Molly"))
randomElement(List(1,2,3))
randomElement(List(1.0,2.0,3.0))
randomElement(Vector.range('a', 'z'))
45
Variable inc is now a function that can be used the usual way −
var x = inc(7)-1
Variable mul is now a function that can be used the usual way −
println(mul(3, 4))
Variable userDir is now a function that can be used the usual way −
println(userDir)
46
Alternatively, you can also use the following syntax to define a curried function −
Syntax
def strcat(s1: String) = (s2: String) => s1 + s2
You can define more than two parameters on a curried function based on your requirement.
Example
object CurrExample {
def main(args: Array[String]) {
val str1:String = "Hello,"
val str2:String = "Scala!"
println("str1 + str2 = " + strcat(str1)(str2) )
}
def strcat(s1: String)(s2: String) = {
s1 + s2
}
}
Output
str1 + str2 = Hello, Scala!
47
13. Closures
A closure is a function, whose return value depends on the value of one or more variables declared
outside this function.
The following piece of code with anonymous function.
val multiplier = (i:Int) => i * 10
Here the only variable used in the function body, i * 10 , is i, which is defined as a parameter to the
function. Try the following code −
val multiplier = (i:Int) => i * factor
There are two free variables in multiplier: i and factor. One of them, i, is a formal parameter to the
function. Hence, it is bound to a new value each time multiplier is called.
However, factor is not a formal parameter, then what is this? Check on the code below.
var factor = 3
val multiplier = (i:Int) => i * factor
Now factor has a reference to a variable outside the function but in the enclosing scope. The function
references factor and reads its current value each time.
If a function has no external references, then it is trivially closed over itself. No external context is
required.
From the point of view of the above function, factor is a free variable, because the function literal
does not itself give a meaning to it. The i variable, by contrast, is a bound variable, because it does
have a meaning in the context of the function: it is defined as the function’s lone parameter, an Int .
Example
object ClosureDemo {
def main(args: Array[String]) {
println( "multiplier(1) value = " + multiplier(1) )
println( "multiplier(2) value = " + multiplier(2) )
}
var factor = 3
val multiplier = (i:Int) => i * factor
}
48
Output
multiplier(1) value = 3
multiplier(2) value = 6
The function value (the object) that’s created at runtime from this function literal is called a closure.
The name arises from the act of “closing” the function literal by “capturing” the bindings of its free
variables.
49
Byte —> Short —> Int —> Long —> Float —> Double
^
|
Char
The arrows denote that a given value type on the left-hand side of the arrow can be promoted to the
right-hand side.
For example, a Byte can be promoted to a Short. The opposite, however, is not true. Scala will not
allow us to assign in the opposite direction:
Now, let’s use those classes to see how type casting via asInstanceOf[T] works:
val t2 = new T2
val t3 = new T3
val t1: T1 = t2.asInstanceOf[T1]
assert(t2.isInstanceOf[T1] == true)
50
assert(t3.isInstance[T1] == false)
val anotherT1 = t3.asInstanceOf[T1] // Run-time error
$ scala hello.scala
51
Here "James" are passed as a command line argument, which is accessed in the script as args(0) .
Here "76" are passed as a command line argument, which is accessed in the script as args(0) .
52
REVISION QUESTIONS
1. In your commodity hardware, what do you need to install inorder to work with scala
2. What do you need to install inorder to work with apache spark?
3. What languages can ypou use to write apache spark jobs.?
4. A java code compile to a byte code what about a scala program.
5. A scala compiled code can run anyhwere in any machine as long as the machine
………………...installed
6. Scala is a hybrid programming language.. What does this mean.
7. What do we mean when we say that a function is a first class function?
8. What do we mean when we say that a function should not have any side effects?
i. Give three examples of such functions
9. Give an example of data structures in Java that are immutable?
10. Give an example of data structures in Scala that are immutable?
11. Scala does not allow you to provide type information when declaring variables. T/F. Explain
you answer.
12. You can have the full joy of programming as a java developer if write you code in scala but
maintain java coding style and syntax throughout . No/Yes. Explain.
13. What happens when you use a scala class for a data type such as Int, Boolean, Double etc when
you compile.
14. All scala data types listed above are objects but not primitive types like in Java. (T/F)
15. Write a scala program that makes use a a variable-argument function that enables one to pass
through any number of integers then print out the integers and the total sum.
Solution
object IntDemo {
def main(args: Array[String])= {
printInts(1,20,30,50,23,60);
}
def printInts( args:Int* ) = {
var i : Int = 0; Int sum=0;
for( arg <- args ){
sum=sum+args
println("Arg value[" + i + "] = " + arg );
i = i + 1;
}
println("{Totals " ] = " + sum );
}
53
}
16. Distinguish between a variable argument function and a nested function.
17. Write a scala program that makes use a nested function grade() that receives the marks passed
and returns the corresponding grade according to a define grading creteria. The function can be
nested inside another function let say printResults() that prints marks scored and the
corresponding grade.
18. Write a scala program that makes use a variable length function printResults() that receives a
variable set of marks and for each mark it prints the corresponding grade according to a define
grading creteria. The program uses a nested function grade() inside the printResults()
function. The nested function recieves every mark passed and returns the grade.
Solution
object FunctionsDemo {
def main(args: Array[String])= {
printResults(36,37,55,20,30,50,23,60);
}
// The variable length function that can receive any number of integers as argument
def printResults( args:Int* ) = {
var i : Int = 0;
for( arg <- args ){
println("Arg value[" + i + "] = " + arg+ "Grade= "+grade(arg) );
i = i + 1;
}
// A nested function to return the grade for a given marks that returns a string grade
def grade(mark:Int): String={
if( mark >= 70 )"A" else if( mark >= 60 )"B" else if( mark >= 50 )"C" else if( mark
>= 40 )"D" else "F"
}//End of grade
}//End of printResults
}
19. Write a scala program that makes use a anonymous function that receives a variable
marks and for each mark it prints the corresponding grade according to a define
grading creteria.