Functional Objects & Function and Closures

Embed Size (px)

Citation preview

  1. 1. Functional Objects&Function and Closures < Sandip Kumar > [email protected]
  2. 2. Programming with Functional Objects inScalaScala 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 awesomepower of the Actor model.
  3. 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. 4. What is the Functional Object5-When we create a variable whose value is a functionobject and we then reference that variable followed byparentheses, that gets converted into a call to the applymethod of the function object.6-When we treat a method as a function, such as byassigning it to a variable, Scala actually creates afunction object whose apply method calls the originalmethod, and that is the object that gets assigned to thevariable. class test {def m1(x:Int) = x+3 val f1 = (x:Int) => x+3}
  5. 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. 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. 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 bodyreturn [expr]}
  8. 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. 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. 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. 11. Fun With Scala Functionsscala> method1method1scala> method2("abc")method2: abcscala> method3("abcdefg")
  12. 12. Fun With Scala Functions* When we type def method1() = {} we actuallydeclared an instance of a special class. Ill 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 = scala> method1res1: java.lang.Object with () => Unit = scala> method1.applymethod1scala> method1()
  13. 13. #We instantiate an instance of traitFunction0[Unit] and implement its oneabstract method, called apply, and assignit to a val named method1. Now you cansee method1 is actually just a plain oldScala object. When we type in method1and hit enter, the interpreter just tells usthe resulting value of the statement whichis an Object with trait Function0. Hmm,that didnt work. Next we try calling theapply method on the object.
  14. 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. 15. scala> def method2 = { println("method2") }method2: Unitscala> val m2: () => Unit = method2:5: error: type mismatch;found : Unitrequired: () => Unitval m2: () => Unit = method2^scala> def method2() = { println("method2") }method2: ()Unit
  16. 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 weretrying 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, weve 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. 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 inmethod1 and hit enter, the interpreter just tellsus the resulting value of the statement which isan Object with trait Function0. Hmm, that didntwork.
  18. 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. 19. How can we use traitstrait Function3[-T1, -T2, -T3, +R] extends AnyRef{...def apply( v1 :T1, v2 :T2, v3 :T3 ) : R...}
  20. 20. Fun With Scala Functionsscala> def method2 = { println("method2") }method2: Unitscala> val m2: () => Unit = method2:5: error: type mismatch;found : Unitrequired: () => Unitval m2: () => Unit = method2 ^* we just define a function called method2.
  21. 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, weve againremoved the parentheses. But this time weassign it successfully to val m2 by following
  22. 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. 23. FunctionsCall-by-Nameobject Test { def main(args: Array[String]) { delayed(time()); } def time() = {
  24. 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. 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 x*yVariable mul is now a function that can be used the
  26. 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:
  27. 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}}
  28. 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.
  29. 43. Scala - Closuresobject Test {def main(args: Array[String]) {println( "muliplier(1) value = " + multiplier(1) )println( "muliplier(2) value = " + multiplier(2) )}var factor = 3val multiplier = (i:Int) => i * factor}Above function references factor and reads its current value each time. If a
  30. 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
  31. 45. Thank you