2. What is Functional Programming
It must be true: x == y <==> f( x ) == f( y )
In a functional language, a function is a value of the same status as, say,
an integer or a string.
Eg :1+2 OR Matrix1+ Matrix2
You can pass functions as arguments to other functions & return them as
results from functions,or store them in variables.
Define a function inside another function.
Define functions without giving them a name.
3. What is Functional Object
Functional objects is a objects that do not have any mutable state.
Immutable objects not have complex state spaces that change
over time.
We can pass immutable objects whereas we may need to make
defensive copies of mutable objects before passing them to other
code.
No thread can change the state of an immutable object.
4. Function Currying in Scala
Currying is the technique of transforming a function that takes multiple
arguments into a function that takes a single argument.
Eg:
def add(x:Int, y:Int) = x + y
And after currying:
def add(x:Int) = (y:Int) => x + y
Add(1)(2) // 3
The second example redefines the add method so that it takes only a single
Int as a parameter and returns a functional (closure) as a result.
5. Partials v/s Currying
Partial Function Currying
def add(x:Int, y:Int, z:Int) = x + y + z def add(x:Int, y:Int, z:Int) = x + y + z
val addFive = add(5, _:Int, _:Int) val addFive = (a:Int, b:Int) => add(5, a, b)
Scala> addFive(3, 1) //9 Scala> addFive(3, 1) // 9
6. Constructing a Rational Object
class Rational(n: Int, d: Int)
here n & d are class parameters.
The Scala compiler will gather up these two class parameters and create a
primary constructor that takes the same two parameters.
scala> new Rational(1, 2)
res0: Rational = Rational@90110a
7. Reimplementing the toString method
We can override the default implementation by adding a method toString to
class Rational, like this:
class Rational(n: Int, d: Int) {
override def toString = n +"/"+ d
}
scala> val x = new Rational(1, 3)
x: Rational = 1/3
8. Checking preconditions
class Rational(n: Int, d: Int) {
require(d != 0)
override def toString = n +"/"+ d
}
The require method takes one boolean parameter.
require will prevent the object from being constructed by throwing an
IllegalArgumentException.
9. Adding Fields
//won't compile
class Rational(n: Int, d: Int) {
require(d != 0)
override def toString = n +"/"+ d
def add(that: Rational): Rational =
new Rational(n * that.d + that.n * d, d * that.d)
}
Here add method is the field
that.n or that.d, because that does not refer to the Rational
object on which add was invoked
10. //here is the correct example
class Rational(n: Int, d: Int) {
require(d != 0)
val numer: Int = n
val denom: Int = d
override def toString = numer + "/" + denom
def add(that: Rational): Rational =
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom)
}
11. scala> val rational = new Rational(1, 2)
rational: Rational = ½
scala> rational.numer
res1: Int = 1
scala> rational.denom
res2: Int = 2
scala> val oneHalf = new Rational(1, 2)
oneHalf: Rational = ½
scala> val twoThirds = new Rational(2, 3)
twoThirds: Rational = 2/3
scala> oneHalf add twoThirds // oneHalf.add(twoThirds)
res3: Rational = 7/6
12. Self references
this refers to the self reference .
def add(that: Rational): Rational =
new Rational( this.numer * that.denom + that.numer * this.denom,
this.denom * that.denom)
scala> val oneHalf = new Rational(1, 2)
oneHalf: Rational = ½
scala> val twoThirds = new Rational(2, 3)
twoThirds: Rational = 2/3
scala> oneHalf add twoThirds
res3: Rational = 7/6
13. Auxiliary constructors
In Scala, constructors other than the primary constructor are called
auxiliary constructors.
Auxiliary constructors in Scala start with def this(...)
class Rational(n: Int, d: Int) {
def this(n: Int) = this(n, 1) // auxiliary constructor
}
scala> val rational = new Rational(3)
rational: Rational = 3/1
14. Private fields and methods
class Rational(n: Int, d: Int) {
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
def this(n: Int) = this(n, 1)
override def toString = numer +"/"+ denom
private def gcd(a: Int, b: Int): Int =
if (b == 0) a else gcd(b, a % b)
}
scala> new Rational(50,10)
res1: Rational = 5/1
15. Defining operators
We can write operation(+,*,-,/.....) on functional object as same as integer
object like
eg def + (that: Rational): Rational =
new Rational(numer * that.denom + that.numer * denom,
denom * that.denom)
scala> onehalf + twothird //onehalf.+(twothird)
res1: Rational = 7/6
It is same as 1+2 or 1*2
16. Scala’s also follows the rules for operator precedence.
Eg:
x + x * y will execute as x + (x * y), not (x + x) * y:
scala>oneHalf + oneHalf * twoThirds
res1: Rational = 5/6
The above expression will evaluated as
oneHalf.+(oneHalf.*(twoThirds))
18. Implicit conversions
OneHalf * 2 // compile because it convert into OneHalf.*(2)
2 * OneHalf // won't compile because it convert into 2.*(OneHalf)
To resolve this implicit conversion is used.
scala> implicit def intToRational(x: Int) = new Rational(x)
This defines a conversion method from Int to Rational.
scala> val r = new Rational(2,3)
r: Rational = 2/3
scala> 2 * r
res1: Rational = 4/3
19. Object Equality
The == equality is reserved in Scala for the“natural” equality of each type.
For value types, == is value comparison.
We can redefine the behavior of == for new types by overriding the equals
method,which is always inherited from class Any.
It is not possible to override == directly, as it is defined as a final method in
class Any.
If two objects are equal according to the equals method, then calling the
hashCode method on each of the two objects must produce the same integer
result.
Eg:
var r1=new Rational(1,2)
var r2=new Rational(-1,2)
scala> r1 equals r2 //false
20. Example of equality on Rational
class
override def equals(other: Any): Boolean =
other match {
case that: Rational =>
(that canEqual this) &&
numer == that.numer &&
denom == that.denom
case _ => false
}
def canEqual(other: Any): Boolean =
other.isInstanceOf[Rational]
override def hashCode: Int =
41 * (
41 + numer) + denom