Scala and functional programming
I have recently moved to programming in Scala. I started with 1 book and have now completed Functional Programming Principles in Scala , a free course on coursera. I am also part way into the next course on Principles of Reactive Programming.So far I have been having a ton of fun, and been blown away at the power of functional programming. I wanted to share some notes that helped me to understand some of the topics that I have studied.Introduction to Currying in Scala
What is Currying
Currying is named after "Haskell Brooks Curry" a mathematician and logician.
Looking at A Tour of Scala: Currying: "Methods may define multiple parameter lists. When a method is called with a fewer number of parameter lists, then this will yield a function taking the missing parameter lists as its arguments."
Currying is a way of applying partial functions in an effort to make your code operate or appear more like built in language constructs thus making it more readable.
Here is some text from the book "Programming in Scala: A Comprehensive Step-by-Step Guide"
Currying allows you to make new control abstractions that feel like native language.... and, A curried function is applied to multiple arguments lists instead of just one.
Partial Functions
To better understand Currying we must take a look at partial functions. Functions in Scala and other functional languages are first class objects. These objects are generated for you by the compiler and contain a method
apply.  When you call a function
def f = {}
f()        // you are actually calling f.apply()
def mul3( a: Int, b: Int, c:Int ): Int = {
 a * b * c
}                                         // mul3: (a: Int, b: Int, c: Int)Int
mul3( 2, 2, 2)                            // res0: Int = 8
val partial = mul3( 5, _: Int , 5 )       // partial  : Int => Int = >function1<
def f1( b: Int ): Int = {
   mul3(5, b, 5)
}
So now that we have some background lets take a look at a curried function. We will write a function prod and then show the equivalent curried function curriedProd
def prod( a: Int, b: Int) = { a * b }     //> prod: (a: Int, b: Int)Int
def curriedProd(a: Int)( b: Int) = { a * b }
                                                  //> curriedProd: (a: Int)(b: Int)Int
val timesThree = curriedProd(3)_          //> timesThree  : Int => Int = 
 
val result = timesThree(3)                //> result  : Int = 9                                                  //> curriedProd: (a: Int)(b: Int)Int
 
Function Calling Syntax
Lets again define a simple function. This function takes a single parameter and adds five to its value. There are actually 2 different function calling syntax (there are actually more then 2). One that uses the normal parenthesis for arguments () and another method that uses curly braces or block syntax {}. Lets take a look at an example
def plusFive( x: Int ) = {
  x + 5
 }                                         //> plusFive: (x: Int)Int
 
val b = plusFive(10)                      //> b  : Int = 15
val c = plusFive{ 10 }                    //> c  : Int = 15
def applyOpt( a: Int, b: Int, op: (Int, Int) => Int) = {
  op( a, b )
 }                                         //> applyOpt: (a: Int, b: Int, op: (Int, Int) => Int)Int
 
 applyOpt( 3, 3, (a: Int, b: Int) => { a * b } )
                                                  //> res2: Int = 9
 
 
 
 def applyOpt2( a: Int, b: Int)(op: (Int, Int) => Int) = {
  op( a, b )
 }                                         //> applyOpt2: (a: Int, b: Int)(op: (Int, Int) => Int)Int
 
 
 applyOpt2( 4, 4 ){ (a,b) => a*b }         //> res3: Int = 16// or even..applyOpt2( 4, 4 ){ _ * _ }                //> res3: Int = 16
Now that we have seen how this works it is time to put it all together in a real world example.
The Loan Pattern
The loan pattern is a way of lending resources to the caller while managing the lifecycle of those resources when they are no longer used. Coming from a C# background this is exactly the purpose of the "using" key word in C# .net
Lets finish off with a concrete example of this pattern in action.
def withOutput(f: OutputStream => Any) {
  val out: OutputStream = getOutputStream()
 
  try {
    f(out)
    out.flush()
  }
  finally {
    out.close() 
  }
}
// Now we can write...
withOutput { out => out.write(response.getBytes()) }
 
No comments:
Post a Comment