4. Conditional and Value Definition
- Sample :
val <identifier>[: <type>] = <expression>
var <identifier>[: <type>] = <expression>
- If Expressions
if (<Boolean expression>) <expression>
- If-Else Expressions
if (<Boolean expression>) <expression>
else <expression>
- Match Expressions
<expression> match {
case <pattern match> => <expression>
[case...]
}
- A Pattern Alternative :
case <pattern 1> | <pattern 2> .. => <one or more expressions>
- Matching with Wildcard Patterns
case <identifier> => <one or more expressions>
- Matching with Pattern Guards
case <pattern> if <Boolean expression> => <one or more
expressions>
- Match Expressions
<expression> match {
case <pattern match> => <expression>
[case...]
}
Source : Safaribooksonline.com
5. Example
- If Expressions
if (10%2 == 0) println(“10 is a multiple of 2”)
- If-Else Expressions
val x = 10;
val y = 5
if (x > y) println(“Max number is :”+ x)
else println(“Max numner is :” + y)
- Match Expressions
val x = 10;
val y = 5;
val max = x > y match {
case true => x
case true => y
}
- A Pattern Alternative :
val day = “MON”
val kind = day match {
case “MON”| ”TUE” | “WED” | “THU” | “FRI”
=>
“weekday”
case “SAT” | “SUN” =>
“weekend”
}
- Matching with Wildcard Patterns
case _ => {println(s”Couldn’t parse $message”) -1}
- Matching with Pattern Guards
case 3 if 3 > 5=> println(“Something”)
Source : Safaribooksonline.com
6. Blocks
val x = 0
def f(y: Int) = y + 1
val result = {
val x = f(3)
x * x
} + x
- A block is delimited by braces { ...
}
- It contains a sequence of
definitions or expressions
- Blocks are themselves
expressions; a block may appear
everywhere an expression can
- The definitions inside a block are
only visible from within the block.
7. Tail recursion
- Recursion definition : A call B, B call A ..etc
- Reasons we don’t see alot of recursion code in Java
- is hard ( is not intuitive : you see one layer and you have to
imagine what happens when those layers stack up)
- is not designed to accommodate recursion. It’s designed to
accommodate iteration.
- But in Scala, being a function language is very much geared toward
recursion rather than iteration ( Scala in the case of tail recursive,
can eliminate the creation of a new stack frame and just re-use the
current stack frame)
8. Example
def pascal(c: Int, r: Int): Int = {
if(c == 0) return 1
if(c == 1 && c != r) return r
if(c == r) return 1
pascal(c-1,r-1)+pascal(c,r-1)
}
9. Tail&Head recursion in Scala
def listLength2(list: List[_]): Int =
{
def listLength2Helper(list: List[_],
len: Int): Int = {
if (list == Nil) len
else listLength2Helper(list.tail,
len + 1)
}
listLength2Helper(list, 0)
}
var list1 = List(1, 2, 3, 4, 5, 6, 7,
8, 9, 10)
println( listLength2( list1 ) )
def listLength1(list: List[_]): Int =
{
if (list == Nil) 0
else 1 + listLength1(list.tail)
}
var list1 = List(1, 2, 3, 4, 5, 6, 7,
8, 9, 10)
println( listLength1( list1 ) )
11. Higher-order function
Scala allows the definition of higher-order
functions.
- Functions can take other functions as
parameters
- Result is a function
- Example
13. Currying Functions
Currying transforms a function that takes
multiple parameters into a chain of function,
each taking a single parameter. Curried
functions are defined with multiple parameter
lists, as follows :
def strcat(s1: String)(s2: String) = s1 + s2
OR
def strcat(s1: String) = (s2: String) => s1 + s2
17. Trait and Abstract class
- Scala has traits, and a trait is more flexible than an abstract class, so you
wonder, “When should I use an abstract class?”
- Reason is :
- You want to create a base class that requires constructor arguments
- The code will be called from Java code
- We can use
abstract class Animal(name: String)
- But we can’t use
trait Animal(name: String)
18. Trait ( The reason we should use trait )
- One big advantage of traits is that you can extend multiple traits but only
one abstract class. Traits solve many of the problems with multiple
inheritance but allow code reuse.
- Define types by specifying the signatures of supported methods.
This is similar to how interfaces work in Java.
But trait can’t
- Traits do not have constructor parameters (but this should not be an issue in practice).
- Traits impose a slight performance overhead (but this is unlikely to impact the overall
performance of your program)
- Traits introduce compilation fragility for classes that mix them in. If a trait changes, a class that
mixes it in has to be recompiled
19. Exercises
- Pascal’s Triangle
The following pattern of numbers is called Pascal’s triangle.
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
...
The numbers at the edge of the triangle are all 1, and each number inside the triangle is the sum of the two numbers above it. Write a function
that computes the elements of Pascal’s triangle by means of a recursive process.
Do this exercise by implementing the pascal function in Main.scala, which takes a column c and a row r, counting from 0 and returns the number
at that spot in the triangle. For example: pascal(0,2)=1, pascal(1,2)=2 and pascal(1,3)=3.
def pascal(c: Int, r: Int): Int
Source : coursera.org
20. Exercises
object Main {
def main(args: Array[String]) {
println("Pascal's Triangle")
for (row <- 0 to 10) {
for (col <- 0 to row)
print(pascal(col, row) + " ")
println()
}
def pascal(c: Int, r: Int): Int = {
c match {
case 0 => 1
case 1 if c == 1 && c != r => r
case r => 1
case _ => pascal(c-1,r-1)+pascal(c,r-1)
}
}
}
There are two basic kinds of recursive: head recursive and tail recursive. In head recursion and tail recursion. In head recursion, a function makes its recursive call and then performs some more calculations, maybe using the result of the recursive call. In a tail recursive function, all calculations happen first and the recursive call is the last thing that happens
This won’t work with head recursive. Because : First it does some work, then it makes its recursive call, then it does a little more work. We can’t just re-use the current stack frame when we make that recursive call. We’re going to NEED that stack frame into after the recursive call completes
http://meetfp.com/en/scala-basic/class-hierarchy
http://www.artima.com/pins1ed/scalas-hierarchy.html
Any is the top class, which means, every other class inherits from Any, therefor every object can invoke methods provided by Any. Those methods are as following.
Null is a subtype of all reference type, and Nothing is a subtype of all other classes
The root class Any has two subclasses: AnyVal and AnyRef. AnyVal is the parent class of every built-in value class in Scala. There are nine such value classes: Byte,Short, Char, Int, Long, Float, Double, Boolean, and Unit. The first eight of these correspond to Java's primitive types, and their values are represented at run time as Java's primitive values. The instances of these classes are all written as literals in Scala. For example, 42 is an instance of Int, 'x' is an instance of Char, and false an instance ofBoolean. You cannot create instances of these classes using new. This is enforced by the "trick" that value classes are all defined to be both abstract and final
The other subclass of the root class Any is class AnyRef. This is the base class of all reference classes in Scala. As mentioned previously, on the Java platform AnyRef is in fact just an alias for class java.lang.Object. So classes written in Java as well as classes written in Scala all inherit from AnyRef.[1] One way to think of java.lang.Object, therefore, is as the way AnyRef is implemented on the Java platform. Thus, although you can use Object and AnyRef interchangeably in Scala programs on the Java platform, the recommended style is to use AnyRef everywhere.
Class Null is the type of the null reference; it is a subclass of every reference class (i.e., every class that itself inherits from AnyRef). Null is not compatible with value types.You cannot, for example, assign a null value to an integer variable:
scala> val i: Int = null <console>:4: error: type mismatch; found : Null(null) required: Int
Type Nothing is at the very bottom of Scala's class hierarchy; it is a subtype of every other type. However, there exist no values of this type whatsoever. Why does it make sense to have a type without values? As discussed in Section 7.4, one use of Nothing is that it signals abnormal termination. For instance there's the error method in thePredef object of Scala's standard library, which is defined like this:
def error(message: String): Nothing = throw new RuntimeException(message)
If you plan to distribute it in compiled form, and you expect outside groups to write classes inheriting from it, you might lean towards using an abstract class. The issue is that when a trait gains or loses a member, any classes that inherit from it must be recompiled, even if they have not changed. If outside clients will only call into the behavior, instead of inheriting from it, then using a trait is fine.