Functional object

21
Ruchi Jindal Software Consultant Knoldus Introducing Functional Objects

description

 

Transcript of Functional object

Page 1: Functional object

Ruchi Jindal Software Consultant

Knoldus

Introducing Functional Objects

Page 2: Functional object

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.

Page 3: Functional object

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.

Page 4: Functional 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.

Page 5: Functional object

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

Page 6: Functional object

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

Page 7: Functional object

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

Page 8: Functional object

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.

Page 9: Functional object

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

Page 10: Functional object

//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)}

Page 11: Functional object

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

Page 12: Functional object

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

Page 13: Functional object

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

Page 14: Functional object

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

Page 15: Functional object

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

Page 16: Functional object

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))

Page 17: Functional object

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)

Page 18: Functional object

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

Page 19: Functional object

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

Page 20: Functional object

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

Page 21: Functional object