scala oo (1)

Download Scala oo (1)

If you can't read please download the document

Upload: sandip-kumar

Post on 16-Apr-2017

617 views

Category:

Technology


1 download

TRANSCRIPT

PowerPoint Presentation




Functional Objects
&
Function and Closures

< Sandip Kumar > [email protected]

Programming with Functional Objects in Scala

Scala is the perfect mixture of Object Oriented (OO) and Functional Programming (FP). You get the flexibility of FP along with the familiarity of OO; along with the awesome power of the Actor model.




What is the Functional Object

1- A function in Scala is a complete object. There are a series of traits in Scala to represent functions with various numbers of arguments: Function0, Function1, Function2, etc

2- As an instance of a class that implements one of these traits, a function object has methods3-One of these methods is the apply method, which contains the code that implements the body of the function.4-Scala has special "apply" syntax: if you write a symbol name followed by an argument list in parentheses (or just a pair of parentheses for an empty argument list), Scala converts that into a call to the apply method for the named object.

What is the Functional Object

5-When we create a variable whose value is a function object and we then reference that variable followed by parentheses, that gets converted into a call to the apply method of the function object. 6-When we treat a method as a function, such as by assigning it to a variable, Scala actually creates a function object whose apply method calls the original method, and that is the object that gets assigned to the variable.

class test {

def m1(x:Int) = x+3

val f1 = (x:Int) => x+3

}

What is the Functional Object

Scala has both functions and methods and we use the terms method and function interchangeably with a minor difference.

# A Scala method is a part of a class which has a name, a signature, optionally some annotations, and some bytecode where as a function in Scala is a complete object which can be assigned to a variable.

# In other words, a function which is defined as a member of some object is called a method.

Scala is a functional language, in the sense that every function is a Value. If functions are values, and values are objects, it follows that functions themselves are objects. The function type S => T is equivalent to scala.Function1[S, T] where Function1 is defined as

------------------------------------------------------------------------------------------------------

trait Function1[-S, +T] {

def apply(x: S): T

}

So functions are interpreted as objects with apply methods.For example, the anonymous successor function (x: Int ) => x + 1 is expanded to

--------------------------------------------------------------------------------------------------------

new Function1[Int, Int] {

def apply(x: Int): Int =

x+1

}

Function Declarations:

A scala function declaration has the following form:

def functionName ([list of parameters]) : [return type]

Function Definitions:

A scala function definition has the following form:

def functionName ([list of parameters]) : [return type] = {

function body

return [expr]

}

Function Implementation

A function which does not return anything can return Unit which is equivalent to void in Java and indicates that function does not return anything. The functions which do not return anything in Scala, they are called procedures. Following is the syntax

object Hello{

def printMe( ) : Unit = {

println("Hello, Scala!")

}

}

Calling Functions:

Scala provides a number of syntactic variations for invoking methods. Following is the standard way to call a method:

functionName( list of parameters )

If function is being called using an instance of the object then we would use dot notation similar to Java as follows:[instance.]functionName( list of parameters )object Test { def main(args: Array[String]) { println( "Returned Value : " + addInt(5,7) ); } def addInt( a:Int, b:Int ) : Int = { var sum:Int = 0 sum = a + b

return sum }}

Fun With Scala Functions

scala> def method1() = { println("method1") }

method1: ()Unit

scala> def method2(str: String) = { println("method2: " + str) }

method2: (String)Unit

scala> def method3(str: String): Int = {

| println("method3: " + str); str.length;

| }

method3: (String)Int

scala> def method4(f: (String) => Int) = {

| printf("method4: " + f("method4"))

| }

method4: ((String) => Int)Unit

Fun With Scala Functions

scala> method1

method1

scala> method2("abc")

method2: abc

scala> method3("abcdefg")

method3: abcdefg

res13: Int = 7

Fun With Scala Functions

* When we type def method1() = {} we actually declared an instance of a special class. Ill declare method1 again, but with the underlying object exposed:

scala> val method1 = new Function0[Unit] {

| def apply: Unit = { println("method1") }

| }

method1: java.lang.Object with () => Unit =

scala> method1

res1: java.lang.Object with () => Unit =

scala> method1.apply

method1

scala> method1()

method1

#We instantiate an instance of trait Function0[Unit] and implement its one abstract method, called apply, and assign it to a val named method1. Now you can see method1 is actually just a plain old Scala object. When we type in method1 and hit enter, the interpreter just tells us the resulting value of the statement which is an Object with trait Function0. Hmm, that didnt work. Next we try calling the apply method on the object.

#But its just a regular call to a member method. But when we type method1() then Scala knows that we want to use this object as a function, and that were not refering to the object itself. When you declare a function using def Scala assumes that when you refer to the method you want the apply method invoked, and that you dont want to return the function object. Neat.

That Function0[Unit], by the way, defines a function that takes 0 parameters and returns Unit (which is to say nothing as in Java void (not to be confused with Nothing)). If you want a function that takes two parameters, an Int and a String, and returns a List of Doubles, you would use Function2[Int, String, List[Double]]. So class FunctionX takes (X+1) type parameters, the first X of which define the function parameter types, and the last of which defines the return type.

scala> def method2 = { println("method2") }

method2: Unit

scala> val m2: () => Unit = method2

:5: error: type mismatch;

found : Unit

required: () => Unit

val m2: () => Unit = method2

^scala> def method2() = { println("method2") }

method2: ()Unit

scala> val m2: () => Unit = method2

m2: () => Unit =

scala> def method2 = { println("method2") }

method2: Unit

scala> val m2: () => Unit = method2 _

m2: () => Unit =

# First we just define a function called method2. Nothing fancy. Then we try to assign it to a val of type () => Unit. It fails. See the error message? Found : Unit. It parses it all wrong. Scala thinks were trying to call method2 and assign the result to m2. How can we set things straight? Well, one way is to slightly change the way we define method2. The only difference in the first and second definition is the addition of an empty parameter list, that empty pair parentheses.

# For some reason, when we define the method in this apparently equivalent fashion, Scala rightly interprets our intentions and allows us to assign to m2. There is another way, though. In the third definition of method2, weve again removed the parentheses. But this time we assign it successfully to val m2 by following method2 with an underscore. The underscore just causes Scala to treat method2 as a Function0 object, rather than attempting to invoke it.

Fun With Scala Functions

1-We instantiate an instance of trait Function0[Unit] and implement its one abstract method, called apply, and assign it to a val named method1.

2-Now you can see method1 is actually just a plain old Scala object. When we type in method1 and hit enter, the interpreter just tells us the resulting value of the statement which is an Object with trait Function0. Hmm, that didnt work.

3- we try calling the apply method on the object. That works! But its just a regular call to a member method. But when we type method1() then Scala knows that we want to use this object as a function, and that were not refering to the object itself.

4-When you declare a function using def Scala assumes that when you refer to the method you want the apply method invoked, and that you dont want to return the function object. Neat

Fun With Scala Functions

If you want a function that takes two parameters, an Int and a String, and returns a List of Doubles, you would use Function2[Int, String, List[Double]]. So class FunctionX takes (X+1) type parameters, the first X of which define the function parameter types, and the last of which defines the return type.

How can we use traits

trait Function3[-T1, -T2, -T3, +R] extends AnyRef {

...

def apply( v1 :T1, v2 :T2, v3 :T3 ) : R

...

}

Fun With Scala Functions

scala> def method2 = { println("method2") }

method2: Unit

scala> val m2: () => Unit = method2

:5: error: type mismatch;

found : Unit

required: () => Unit

val m2: () => Unit = method2

^

* we just define a function called method2. Nothing fancy. Then we try to assign it to a val of type () => Unit. It fails. See the error message? Found : Unit. It parses it all wrong. Scala thinks were trying to call method2 and assign the result to m2. How can we set things straight?

Fun With Scala Functions

1-The only difference in the first and second definition is the addition of an empty parameter list, that empty pair parentheses. For some reason, when we define the method in this apparently equivalent fashion, Scala rightly interprets our intentions and allows us to assign to m2.

2- In the third definition of method2, weve again removed the parentheses. But this time we assign it successfully to val m2 by following method2 with an underscore. The underscore just causes Scala to treat method2 as a Function0 object, rather than attempting to invoke it.

So a function is an object

Scala - Functions Call-by-NameA call-by-name mechanism passes a code block to the callee and each time the callee accesses the parameter, the code block is executed and the value is calculated.

Functions Call-by-Nameobject Test { def main(args: Array[String]) { delayed(time()); }

def time() = { println("Getting time in nano seconds") System.nanoTime } def delayed( t: => Long ) = { println("In delayed method") println("Param: " + t) t }}

Scala - Function with Variable Arguments

Scala allows you to indicate that the last parameter to a function may be repeated. This allows clients to pass variable length argument lists to the function. Following is a simple example to show the concept.

Function with Variable Argumentsobject Test { def main(args: Array[String]) { printStrings("Hello", "Scala", "Python"); } def printStrings( args:String* ) = { var i : Int = 0; for( arg x+1

Variable inc is now a function that can be used the usual way:

var x = inc(7)-1

It is also possible to define functions with multiple parameters as follows:

var mul = (x: Int, y: Int) => x*y

Variable mul is now a function that can be used the usual way:

println(mul(3, 4))

It is also possible to define functions with no parameter as follows:

var userDir = () => { System.getProperty("user.dir") }

Variable userDir is now a function that can be used the usual way:

println( userDir )

Scala - Currying Functions

Currying transforms a function that takes multiple parameters into a chain of functions, each taking a single parameter. Curried functions are defined with multiple parameter lists, as follows:

def strcat(s1: String)(s2: String) = s1 + s2

Alternatively, you can also use the following syntax to define a curried function:

def strcat(s1: String) = (s2: String) => s1 + s2

Following is the syntax to call a curried function:

strcat("foo")("bar")

Scala - Currying Functions

object Test {

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

}

}

Scala - Closures

A closure is a function whose return value depends on the value of one or more variables declared outside this function. Consider the following piece of code with anonymous function:

val multiplier = (i:Int) => i * 10

Here the only variable used in the function body, i * 0, is i, which is defined as a parameter to the function. Now let us take another piece of 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? Let us add one more line of code:

var factor = 3

val multiplier = (i:Int) => i * factor

Scala - Closures

object Test {

def main(args: Array[String]) {

println( "muliplier(1) value = " + multiplier(1) )

println( "muliplier(2) value = " + multiplier(2) )

}

var factor = 3

val multiplier = (i:Int) => i * factor

}

Above 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.

PROBLEM

class TestClass {

| def f1(): Unit = { println("f1!!!"); func = f2 }

| def f2(): Unit = { println("f2!!!"); func = f3 }

| def f3(): Unit = { println("f3!!!"); func = f1 }

|

| var func: () => Unit = f1

|

| def test = { func() }

| }

IF tc is the object of the class than output of

scala> tc.test, scala> tc.test and scala> tc.test

Thank you