Functional Objects  & Function and Closures
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
862
On Slideshare
862
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
24
Comments
2
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Functional Objects &Function and Closures < Sandip Kumar > sandip@knoldus.com
  • 2. Programming with Functional Objects in ScalaScala is the perfect mixture of Object Oriented (OO) andFunctional Programming (FP). You get the flexibility of FPalong with the familiarity of OO; along with the awesome power of the Actor model.
  • 3. What is the Functional Object 1- A function in Scala is a complete object. There are aseries of traits in Scala to represent functions with variousnumbers of arguments: Function0, Function1, Function2, etc 2- As an instance of a class that implements one of thesetraits, a function object has methods3-One of these methods is the apply method, which containsthe code that implements the body of the function.4-Scala has special "apply" syntax: if you write a symbolname followed by an argument list in parentheses (or just apair of parentheses for an empty argument list), Scalaconverts that into a call to the apply method for the namedobject.
  • 4. What is the Functional Object5-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 }
  • 5. What is the Functional Object Scala has both functions and methods and we use theterms method and function interchangeably with a minordifference.# A Scala method is a part of a class which has a name, asignature, optionally some annotations, and some bytecodewhere as a function in Scala is a complete object which canbe assigned to a variable. # In other words, a function which is defined as a member ofsome object is called a method.
  • 6. Scala is a functional language, in the sense that every function is a Value. Iffunctions are values, and values are objects, it follows that functionsthemselves are objects. The function type S => T is equivalent toscala.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, theanonymous successor function (x: Int ) => x + 1 is expanded to--------------------------------------------------------------------------------------------------------new Function1[Int, Int] {def apply(x: Int): Int =x+1
  • 7. 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]}
  • 8. Function ImplementationA function which does not return anything canreturn Unit which is equivalent to void in Java andindicates that function does not return anything.The functions which do not return anything inScala, they are called procedures. Following is thesyntaxobject Hello{ def printMe( ) : Unit = {
  • 9. Calling Functions:Scala provides a number of syntactic variations forinvoking methods. Following is the standard way to calla method:functionName( list of parameters )If function is being called using an instance of theobject then we would use dot notation similar to Javaas follows:[instance.]functionName( list of
  • 10. Fun With Scala Functionsscala> def method1() ={ println("method1") }method1: ()Unitscala> def method2(str: String) ={ println("method2: " + str) }method2: (String)Unitscala> def method3(str: String): Int = {
  • 11. Fun With Scala Functionsscala> method1method1scala> method2("abc")method2: abcscala> method3("abcdefg")
  • 12. Fun With Scala Functions * When we type “def method1() = {…}” we actuallydeclared an instance of a special class. I’ll declare method1again, but with the underlying object exposed:scala> val method1 = new Function0[Unit] { | def apply: Unit = { println("method1") } |}method1: java.lang.Object with () => Unit = <function>scala> method1res1: java.lang.Object with () => Unit = <function>scala> method1.applymethod1scala> method1()method1
  • 13. #We instantiate an instance of traitFunction0[Unit] and implement its one abstractmethod, called apply, and assign it to a valnamed method1. Now you can see method1 isactually just a plain old Scala object. When wetype in “method1″ and hit enter, the interpreterjust tells us the resulting value of the statementwhich is an Object with trait Function0. Hmm,that didn’t work. Next we try calling the applymethod on the object.#But it’s just a regular call to a member method.But when we type “method1()” then Scala knowsthat we want to use this object as a function, andthat we’re not refering to the object itself. Whenyou declare a function using “def” Scala assumes
  • 14. That Function0[Unit], by the way, defines afunction that takes 0 parameters and returns Unit(which is to say nothing as in Java void (not to beconfused with Nothing)). If you want a functionthat takes two parameters, an Int and a String,and returns a List of Doubles, you would useFunction2[Int, String, List[Double]]. So classFunctionX takes (X+1) type parameters, the firstX of which define the function parameter types,and the last of which defines the return type.
  • 15. scala> def method2 = { println("method2") }method2: Unitscala> val m2: () => Unit = method2<console>:5: error: type mismatch;found : Unitrequired: () => Unit val m2: () => Unit = method2 ^scala> def method2() = { println("method2") }method2: ()Unit
  • 16. # First we just define a function called method2. Nothing fancy. Thenwe try to assign it to a val of type () => Unit. It fails. See the errormessage? Found : Unit. It parses it all wrong. Scala thinks we’retrying to call method2 and assign the result to m2. How can we setthings straight? Well, one way is to slightly change the way we definemethod2. The only difference in the first and second definition is theaddition of an empty parameter list, that empty pair parentheses. # For some reason, when we define the method in this apparentlyequivalent fashion, Scala rightly interprets our intentions and allows usto assign to m2. There is another way, though. In the third definition ofmethod2, we’ve again removed the parentheses. But this time weassign it successfully to val m2 by following method2 with anunderscore. The underscore just causes Scala to treat method2 as aFunction0 object, rather than attempting to invoke it.
  • 17. Fun With Scala Functions 1-We instantiate an instance of traitFunction0[Unit] and implement its one abstractmethod, called apply, and assign it to a valnamed method1.2-Now you can see method1 is actually just aplain old Scala object. When we type in“method1″ and hit enter, the interpreter just tellsus the resulting value of the statement which isan Object with trait Function0. Hmm, that didn’twork.
  • 18. Fun With Scala FunctionsIf 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 thefunction parameter types, and the last of whichdefines the return type.
  • 19. trait Function3[-T1, -T2, -T3, +R] extends AnyRef{ ... def apply( v1 :T1, v2 :T2, v3 :T3 ) : R ...}
  • 20. Fun With Scala Functionsscala> def method2 = { println("method2") }method2: Unitscala> val m2: () => Unit = method2<console>:5: error: type mismatch;found : Unitrequired: () => Unit val m2: () => Unit = method2 ^* we just define a function called method2.
  • 21. Fun With Scala Functions1-The only difference in the first and seconddefinition is the addition of an empty parameterlist, that empty pair parentheses. For somereason, when we define the method in thisapparently equivalent fashion, Scala rightlyinterprets our intentions and allows us to assignto m2.2- In the third definition of method2, we’ve againremoved the parentheses. But this time weassign it successfully to val m2 by followingmethod2 with an underscore. The underscorejust causes Scala to treat method2 as a
  • 22. Scala - Functions Call-by-NameA call-by-name mechanism passes a code block to the callee and each time thecallee accesses the parameter, the code block is executed and the value iscalculated.
  • 23. FunctionsCall-by-Nameobject Test { def main(args: Array[String]) { delayed(time()); } def time() = {
  • 24. Scala - Function with Variable ArgumentsScala allows you to indicate that the last parameter to afunction may be repeated. This allows clients to passvariable length argument lists to the function. Following is asimple example to show the concept.
  • 25. Function with Variable Argumentsobject Test { def main(args: Array[String]) { printStrings("Hello", "Scala", "Python"); } def printStrings( args:String* ) = { var i : Int = 0; for( arg <- args ){ println("Arg value[" + i + "] = " + arg ); i = i + 1; }
  • 26. Scala - Default Parameter Values for a FunctionScala lets you specify default values for function parameters. Theargument for such a parameter can optionally be omitted from afunction call, in which case the corresponding argument will befilled in with the default. Following is an example of specifiyingdefault parameters:
  • 27. Default Parameter Values for a Function object Test { def main(args: Array[String]) { println( "Returned Value : " + addInt() ); } def addInt( a:Int=5, b:Int=7 ) : Int = { var sum:Int = 0 sum = a + b return sum } }
  • 28. Scala - Nested FunctionsScala allows you to define functions inside a function and functions defined inside other functions are called local functions. Here is an implementation of a factorial calculator, where we use a conventional technique of calling a second, nested method to do the work
  • 29. Scala - Nested Functions object Test { def main(args: Array[String]) { println( factorial(0) println( factorial(1) ) println( factorial(2) ) println( factorial(3) ) } def factorial(i: Int): Int = { def fact(i: Int, accumulator: Int): Int = { if (i <= 1) accumulator else fact(i - 1, i * accumulator) } fact(i, 1)}}
  • 30. Scala - Partially Applied FunctionsWhen you invoke a function, youre said to be applying thefunction to the arguments. If you pass all the expected arguments,you have fully applied it. If you send only a few arguments, thenyou get back a partially applied function. This gives you theconvenience of binding some arguments and leaving the rest tobe filled in later. Following is a simple example to show theconcept:
  • 31. Scala - Partially Applied Functionsimport java.util.Dateobject Test { def main(args: Array[String]) { val date = new Date log(date, "message1" ) log(date, "message2" ) log(date, "message3" ) }
  • 32. Scala - Partially Applied Functions*Here the log( ) method takes two parameters: date and message. We want to invoke the method multiple times, with the same value for date but different values for message. We can eliminate the noise of passing the date to each call by partially applying that argument to the log( ) method. To do so,# we first bind a value to the date parameter and leave the second parameter unbound by putting an underscore at its place. The result is a partially applied function that weve stored in a variable.
  • 33. Scala - Functions with Named Arguments Named arguments allow you to pass arguments to a function in a different order. The syntax is simply that each argument is preceded by a parameter name and an equals sign. Following is a simple example to show the concept:
  • 34. Functions with Named Argumentsobject Test { def main(args: Array[String]) { printInt(b=5, a=7); } def printInt( a:Int, b:Int ) = { println("Value of a : " + a ); println("Value of b : " + b ); }}
  • 35. Scala - Recursion Functionsobject Test { def main(args: Array[String]) { for (i <- 1 to 10) println( "Factorial of " + i + ": = " + factorial(i) ) } def factorial(n: BigInt): BigInt = { if (n <= 1) 1 else n * factorial(n - 1)
  • 36. Scala - Higher-Order FunctionsScala allows the definition of higher-orderfunctions. These are functions that take otherfunctions as parameters, or whose result is afunction. For example in the following code,apply() function takes another function f and avalue v and applies function f to v:
  • 37. Scala - Higher-Order Functionsobject Test { def main(args: Array[String]) { println( apply( layout, 10) )} def apply(f: Int => String, v: Int) = f(v) def layout[A](x: A) = "[" + x.toString() + "]"}
  • 38. Scala - Anonymous FunctionsScala provides a relatively lightweight syntax fordefining anonymous functions. Anonymousfunctions in source code are called functionliterals and at run time, function literals areinstantiated into objects called function values.Scala supports first-class functions, which meansyou can express functions in function literalsyntax, i.e., (x: Int) => x + 1, and that functions
  • 39. Scala - AnonymousFunctionsvar inc = (x:Int) => x+1Variable inc is now a function that can be used theusual way:var x = inc(7)-1It is also possible to define functions with multipleparameters as follows:var mul = (x: Int, y: Int) => x*yVariable mul is now a function that can be used the
  • 40. Scala - Currying FunctionsCurrying transforms a function that takes multipleparameters into a chain of functions, each takinga single parameter. Curried functions are definedwith multiple parameter lists, as follows:def strcat(s1: String)(s2: String) = s1 + s2Alternatively, you can also use the followingsyntax to define a curried function:
  • 41. Scala - Currying Functionsobject 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 }}
  • 42. Scala - ClosuresA closure is a function whose return value depends onthe value of one or more variables declared outsidethis function. Consider the following piece of code withanonymous function:val multiplier = (i:Int) => i * 10Here 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 * factorThere are two free variables in multiplier: i and factor.One of them, i, is a formal parameter to the function.
  • 43. Scala - Closuresobject 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 afunction has no external references, then it is trivially closed over itself. Noexternal context is required.
  • 44. PROBLEMclass 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 ofscala> tc.test, scala> tc.test and scala> tc.test
  • 45. Thank you