Friday, March 4, 2016

Polymorphic and annonymous functions in Scala

Anonymous functions in Scala are nameless , lightweight functions which can be passed around without any side affects.  They are also called as function literals, lambda functions, lambda expressions or simply lambdas.  (x,y)=>x+y   is an anonymous function which means that the input to the function are two variables and the result will be the sum of them. Another common lambda expression is an underscore form eg _+1 which means the function is an increment function.
Monomorphic functions are those functions which have only one type. Polymorphic functions are functions which are generic and can work for different datatypes. Following example shows the usage of anonymous function, Monomorphic and Polymorphic functions and tail recursion in Scala.

object Demo{
def main(args:Array[Strings]):Unit={
    var arrD= new Array[Double](4)
    arrD(0) = 2.0
    arrD(1) = 4.0
    arrD(2) = 6.0
    arrD(3) = 7.0
    println(binarySearch(arrD,7.0))    
    println(binSearch[Double](arrD, 7.0, (a:Double, b:Double)=> a>b))
}

// Monomorphic binary search with tail recursion
def binarySearch(ds: Array[Double], key: Double): Int = {
    @annotation.tailrec
    def go(low: Int, mid: Int, high: Int): Int = {
      if (low > high) -mid - 1
      else {
        val mid2 = (low + high) / 2
        val d = ds(mid2)
        if (d == key) mid2
        else if (d > key) go(low, mid2, mid2 - 1)
        else go(mid2 + 1, mid2, high)
      }
    }
    go(0, 0, ds.length - 1)
  }


  // return the index of the searched data if found else
  // a negative number if data doesn't exist
  // takes an anonymous function/lambda as a parameter for comparison
  //this is a generic method which takes any data type 
  def binSearch[X]( data: Array[X], key:X , gt: (X,X) => Boolean):Int={
    @annotation.tailrec
    def go(low:Int, mid:Int, high:Int ):Int={
      if( low > high) -mid-1
      else{
        var mid2 = (low + high) /2
        var d= data(mid2)
        val greater = gt(d,key)
        if ( !greater  && !gt(key,d))  mid2
        else if (greater) go(low,mid2,mid2-1) 
        else go(mid2+1,mid2,high )
      }      
    }    
    go(0,0,data.length-1)    
  }
}

Let me know if you have any comments on the same.

Thursday, March 3, 2016

Higher order functions in scala

A function that takes another function as an argument is called a higher order function. Like any other function parameter we give type as Int=>Int which indicates that f expects an integer as input and integer as a return type(........, f:Int=>Int). A complete example is shown which uses a Higher order function and tail recursion.

object Demo{
def main(args:Array[Strings]): Unit ={    
    println(formatResult("Nth febonacci number where value of N is", 5, febonacci))
    println(formatResult("Factorial of ", 7, factorial))
 
  }
  // nth fibonacci number using tail recursions
  def febonacci(n:Int):Int={  
    @annotation.tailrec
    def nextNum(num1: Int, num2:Int, n :Int):Int={
      if(n==0) num2+num1
      else nextNum(num2,num2+num1,n-1)
    }  
   nextNum(0,1,n-2)    
  }

  def factorial(n:Int):Int={
    @annotation.tailrec
    def fact(num:Int, acc:Int):Int={
      if(num<=0) acc
      else fact(num-1, num*acc)
    }  
    fact(n,1)
  }

  def formatResult(name:String, n:Int, g:Int=>Int )={
    val msg="The %s %d is %d"
    msg.format(name,n,g(n))
   
  }
}

Tail Call Recursion in Scala

Recursions are resource intensive and may lead to Stack overflow if processing a huge data set. Tail Recursions help convert a recursion to a simple iteration. Pure Functions comes handy because the function calls are easily replaced by their respective results using substitution model and referential transitivity. Scala is a very powerful language because of such features which help remove the side effects of functions and help define function objects. following are few examples which showcase tail recursions:

// nth fibonacci number using tail recursions
  def feb(n:Int):Int={  
    @annotation.tailrec
    def nextNum(num1: Int, num2:Int, n :Int):Int={
      if(n==0) num2+num1
      else nextNum(num2,num2+num1,n-1)
    }  
   nextNum(0,1,n-2)  
  }


// factorial function
 def factorial(n:Int):Int={
    @annotation.tailrec
    def fact(num:Int, acc:Int):Int={
      if(num<=0) acc
      else fact(num-1, num*acc)
    }  
    fact(n,1)
  }

Awaiting your comments and examples which you tried to convert a recursion to a tail recursion.