Functional object
-
Upload
ruchijindal87 -
Category
Technology
-
view
2.154 -
download
2
description
Transcript of Functional object
Ruchi Jindal Software Consultant
Knoldus
Introducing Functional Objects
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.
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.
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.
Partials v/s Currying
Partial Function
def add(x:Int, y:Int, z:Int) = x + y + z
val addFive = add(5, _:Int, _:Int)
Scala> addFive(3, 1) //9
Currying
def add(x:Int, y:Int, z:Int) = x + y + z val addFive = (a:Int, b:Int) => add(5, a, b)
Scala> addFive(3, 1) // 9
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
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
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.
Adding Fields//won't compile
class Rational(n: Int, d: Int) { require(d != 0)override def toString = n +"/"+ ddef 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 Rationalobject on which add was invoked
//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)}
scala> val rational = new Rational(1, 2)rational: Rational = ½
scala> rational.numerres1: Int = 1
scala> rational.denomres2: 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
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/3scala> oneHalf add twoThirds res3: Rational = 7/6
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
Private fields and methods
class Rational(n: Int, d: Int) {
private val g = gcd(n.abs, d.abs)val numer = n / gval denom = d / gdef 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
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
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 * twoThirdsres1: Rational = 5/6
The above expression will evaluated as
oneHalf.+(oneHalf.*(twoThirds))
Method overloading
scala>oneThird + 2 // oneThird.+(2)res1: Rational = 7/3
def + (that: Rational): Rational =new Rational(numer * that.denom + that.numer * denom,denom * that.denom)
def + (i: Int): Rational =new Rational(numer + i * denom, denom)
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/3scala> 2 * rres1: Rational = 4/3
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
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