Wednesday, 19 October 2016

Scala: An Overview and some key features


Scala is hybrid programming language which provides Object oriented and functional programming features. It is built on top of JVM, you may call it as 'Better Java'. Like in Java, the Scala code is also compiled and converted to .class(byte code) and runs on JVM. You can use or access Java classes inside a Scala program.


 
Scala is a child language which combines some of the good features of Java and Python. Java provides strong Object oriented, efficient memory management(with garbage collection). Python provides functional programming, map-reduce Apis, concise and comprehensive style of coding. Here are some of the features of Scala: 

Everything is Object:   

All the types are defined as object in scala. Even a function is also treated as object and can be passed as an argument( like we see in JavaScript). For eg: 


   1:    def main(args :Array[String]): Unit = {
   2:      var list1: List[Int] = List(87 , 45, 56);
   3:      System.out.println("list1: " + list1);
   4:   
   5:      //passing fn as a parameter
   6:      val list2 = list1.map(incr)
   7:      System.out.println("list2: " + list2);
   8:   
   9:      //passing an anonymous fn as a paramter
  10:      val list3 = list1.map(x => x +1 )
  11:      System.out.println("list3: " + list3);
  12:   
  13:    }
  14:    
  15:    def incr(x: Int) : Int = {
  16:      x +1;
  17:    }
  18:    
Results:
   1:  list1: List(87, 45, 56)
   2:  list2: List(88, 46, 57)
   3:  list3: List(88, 46, 57)
 
Interactive style of coding:  Scala has an interpreter console where you just type in and execute Scala statements. This is one of the feature which is adopted from Python. Useful for quick 'try-out' instead of building/running using eclipse or similar IDEs.


   1:  Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
   2:  Type in expressions for evaluation. Or try :help.
   3:   
   4:  scala> val str ="Scala interpretor" ;
   5:  str: String = Scala interpretor
   6:   
   7:  scala> val str1 = str + " is working" 
   8:  str1: String = Scala interpretor is working
   9:   
  10:  scala> 
Scala Objects:  These are Singleton Object and don't have to instantiate with a new keyword. In scala, everything is Object. Unlike in Java, we can't have a class level static members in Scala. hence we have Singleton objects which is created with 'object' keyword.
 

   1:  object Arithematics {
   2:    def sum(a: Int , b : Int): Int= {
   3:      return a + b;
   4:     
   5:    }
   6:     def subtract(a: Int , b : Int): Int= {
   7:      return a - b;
   8:    }
   9:   
  10:   
  11:   
  12:   
  13:    def main(arrgs: Array[String]) = {
  14:      
  15:      System.out.print("sum : " + Arithematics.sum(10 , 45))
  16:      
  17:    }
 
Traits: Traits are like interfaces in Java, but can have concrete(common implementation) methods. Scala also allows traits to be partially implemented but traits may not have constructor parameters.

   1:   
   2:   
   3:  trait Equal {
   4:     def isEqual(x: Any): Boolean
   5:     def isNotEqual(x: Any): Boolean = !isEqual(x)
   6:  }
   7:   
   8:  class Point(xc: Int, yc: Int) extends Equal {
   9:     // constructor 
  10:    var x: Int = xc
  11:     var y: Int = yc
  12:    // constructor 
  13:     def isEqual(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == y
  14:  }

Scala is a shortcut language(concise): Scala code are very concise and short in size( just like python) and it provide shortcuts like below. Also the variable assignments are type inference which will avoid redundant type declarations. 



   1:    def main(args :Array[String]): Unit = {
   2:      var list1: List[Int] = List(87 , 45, 56);
   3:      System.out.println("list1: " + list1);
   4:        // val list3 = list1.map(x => x +1 )
   5:      val list3 = list1.map(_ + 1) // shortcut 
   6:      // val reduce = list3.reduce((x, y) => x + y );
   7:     val reduce = list3.reduce(_ + _); // shortcut 
   8:      System.out.println("list3: " + list3);
   9:      System.out.println("reduce: " + reduce);
  10:    }
  11:   
  12:  Results:
  13:   
  14:  list1: List(87, 45, 56)
  15:  list3: List(88, 46, 57)
  16:  reduce: 191
 
  

  def incr(x: Int) : Int = {
    x +1; }

  val x = incr(1);

Here the type of 'x' is automatically defined as Int upon the assignment. However this can't be reassigned to other types. Once it is typed to Int, it can be retyped to other type(even in case of var). Unlike in Java, this will reduce redundant type declarations.
 
Closure functions:  Special function which will return values which depends on the variable declared outside of the function. It needn't be a variable, it can be a functional or anonymous  reference as well



   1:  object ClosureEg {
   2:    val factor = 5;
   3:   
   4:    def multiplier(a :Int) : Int = {
   5:      return a * factor;
   6:    }
   7:  }

This helps in achieving a cleaner of way of coding where you would need to separate out the redundant boiler plate code and the trivial code.  It can also be used as a callback function for asynchronous process. Here is some e.g for closure.


   1:   /* With Closure. Here  makeTag() is normal method and closure fn is the 
   2:    * anonymous method inside the makeTag.
   3:    */
   4:   def makeTag(openTag: String, closeTag: String)  = {
   5:        (content: String)  => openTag +content +closeTag;
   6:   }
   7:    /* Cleaner way of coding. To separate the 
   8:     * non-trivial boiler plate code such as creating the Structure of the xml construct and 
   9:       trivial code such injecting the content */
  10:    var table = makeTag("<table>" , "</table>" ) ;
  11:    var tr = makeTag("<tr>" , "</tr>" ) ;
  12:    var td = makeTag("<td>" , "</td>" ) ;
  13:    table(td(tr("Hi")))



   1:    /* With out Closure. Here  makeTag() is a plain method which accepts 
   2:     * all 3 parameters. Here the low level dependencies has to create first 
   3:     * and has to injected in the order. Not a cleaner way of coding. */
   4:    
   5:    def makeTag1(openTag: String, closeTag: String, content: String)  = {
   6:        openTag +content +closeTag;
   7:   }
   8:    
   9:    var tr1 = makeTag1("<tr>" , "</tr>", "Hi" ) ;
  10:    var td1 = makeTag1("<td>" , "</td>",  tr1) ;
  11:    var table1 = makeTag1("<table>" , "</table>", td1 ) ;
  12:    
  13:    

Pattern matching: pattern match includes a sequence of alternatives, each starting with the keyword case. Each alternative includes a pattern and one or more expressions, which will be evaluated if the pattern matches.

   1:      for (value <- 1 to 5) {
   2:        value match {
   3:          case 1 =>    System.out.println("value is " + value);
   4:          case 2 =>    System.out.println("value is " + value);
   5:          case 3 =>    System.out.println("value is " + value);
   6:          case 4 =>    System.out.println("value is " + value);
   7:        }
   8:      }
Pattern matching can be also done with 'case class' which is a special class in Scala. The default constructor, getter/setter, hashcode() , equals(), toString methods would be automatically generated for case class.


   1:   val alice = new Person("Alice", 25)
   2:        val bob = new Person("Bob", 32)
   3:        val charlie = new Person("Charlie", 32)
   4:     
   5:        for (person <- List(alice, bob, charlie)) {
   6:           person match {
   7:              case Person("Alice", 25) => println("Hi Alice!")
   8:              case Person("Bob", 32) => println("Hi Bob!")
   9:              case Person(name, age) => println(
  10:                 "Age: " + age + " year, name: " + name + "?")
  11:           }
  12:        }
  13:     }
  14:     case class Person(name: String, age: Int)
 
 
 
Scala constructors: How does it created and invoked ?
In Scala, constructors work in a different way than in java. There are two kinds of Constructor in Scala. Primary and Auxiliary constructors.
Primary constructor is defined as part of the class parameters. Everything thing except the class method is considered as constructor code.



   1:    class Employee(val id : Int, val firstName : String, val lastName: String ) {
   2:   /* constructor begins.. */
   3:    var fullName = lastName + ", " + firstName ;
   4:    var this.id = id;
   5:    var location = "";
   6:    var age = 0;
   7:   
   8:     /* construction ends */
   9:    def method1() = {
  10:   
  11:    }
  12:  }

Auxiliary constructors are custom constructor which has additional constructor parameters(Optional). This is defined as this(optional constructor parameters). You need to call this(), the primary constructor inside your Auxiliary constructor.


   1:    class Employee(val id : Int, val firstName : String, val lastName: String ) {
   2:   /* constructor begins.. */
   3:    var fullName = lastName + ", " + firstName ;
   4:    var this.id = id;
   5:    var location = "";
   6:    var age = 0;
   7:   
   8:    def this(id : Int, firstName : String, lastName: String, 
   9:        age : Int, location : String) = {
  10:      this(id,firstName,lastName );
  11:      this.age = age;
  12:      this.location = location;
  13:  }
  14:     /* construction ends */
  15:    def method1() = {
  16:   
  17:    }
  18:  }


2 comments: