Monday, June 24, 2013

Stackable modifications in Scala using Traits

abstract class Product {
def get:Double
def put(x:Double)
}
class Computer extends Product {
var price:Double = 0.0
def get = price
def put(x:Double) = price = x
}
class KeyBoard extends Product {
var price:Double = 0.0
def get = price
def put(x:Double) = price = x
}
class PriceProcessor {
var prods:List[Product] = List()
def +(x:Product) = prods::=x

def totalPrice:Double = {
var pri:Double = 0.0
for(prod<-prods) {
pri+=prod.get
}
pri
}
}
trait ApplyDiscount extends Product{
abstract override def put(x:Double) = super.put(x*0.8)
}
trait AddTax extends Product {
abstract override def put(x:Double) = super.put(x - x*0.07)
}
object MixinTraits {

def myTest {

val prod1 = new Computer
prod1.put(1200)
val prod2 = new KeyBoard
prod2.put(80)

val proc1 = new PriceProcessor
proc1+prod1
proc1+prod2

val price1 = proc1.totalPrice
println("PRICE-->"+price1)

val proc2 = new PriceProcessor
val prod3 = new Computer with ApplyDiscount
prod3.put(1200)
val prod4 = new KeyBoard with ApplyDiscount
prod4.put(80)
proc2+prod3
proc2+prod4
val price2 = proc2.totalPrice

println("PRICE WITH DISCOUNT-->"+price2)
val proc3 = new PriceProcessor
val prod5 = new Computer with ApplyDiscount with AddTax
prod5.put(1200)
val prod6 = new KeyBoard with ApplyDiscount with AddTax
prod6.put(80)
proc3+prod5
proc3+prod6
val price3 = proc3.totalPrice

println("PRICE WITH DISCOUNT AND TAX-->"+price3)
}
}
MixinTraits.myTest


//OUTPUT
PRICE-->1280.0
PRICE WITH DISCOUNT-->1024.0
PRICE WITH DISCOUNT AND TAX-->952.32


Concepts:

Mixin Traits: Traits can be used to achieve polymorphism by using it to change the behavior of an object at runtime.
Traits are not just similar to interfaces in java but also have more attributes than interfaces.
Traits can also have concrete methods defined which can be inherited by classes/traits.

eg: abstract class A
   trait T1 extends A
   class B extends A with T1
 
Stackable modifications: A class object can achieve multilevel transformations (or decorations) by mixing it with one or
more traits. The "with" keyword needs to precede each trait the class mixes with. These traits are stacked one
upon the other starting from the right, with the right most being on the top of the stack. The trait get applied
to the class starting from the right and proceeds left ultil all the traits have been used to decorate the class.

As an example:
   abstract class A
   trait T2 extends A
   trait T1 extends A
   class B extends A with T1 with T2
 
   The trait T2 is first applied and then the trait T1 is applied to the class B.
 

Rules to make traits stackable

1) Consider the example:
abstract class A

trait T1 extends A

class B extends A with T1
class C extends A with T1

   The classes B and C extend the abstract class A. Therefore the trait (T1) mixing classes B and C also
   has to extend the abstract class A.

2) The method signature in the trait which is used to change the behaviour/state of the class which it mixes with,
   has to precede with "abstract override"

eg: abstract override def put(x:Double)

3) Mixing a trait with a class can be done in two ways.

a) While creating the class signature:
class A extends T1 //extending a trait

b) While creating the class instance
val val1 = new class A with T1 //mixing a trait


Code explanation:

1) Product is an abstract class with abstract get and put methods.
2) There are two concrete implementations of Product, namely Computer and Keyboard. These
   classes give concrete implementations of get and put methods.
3) The class PriceProcessor calculates the prices of products from a list. The totalPrice method
   iterates through each product from the list and adds the price of it to a variable "pri".
4) the traits ApplyDiscount and AddTax are used to mix with the classes Computer and Keyboard.

Client Code: (object MixingTraits)
//NORMAL CLASS BEHAVIOR
1) prod1 and prod2 are objects of classes Computer and KeyBoard respectively. The put method on these objects are used to set the prices. These objects prod1 and prod2 are added to an instance proc1 of
  the PriceProcessor class using the "+" function. This function adds appends products to a local list
  object prods present in the PriceProcessor class.
2) The totalPrice method on the PriceProcessor object proc1 is called and the total price of a Computer and a Keyboard is calculated.

//MIXING CLASS OBJECTS WITH TRAITS
3) prod3 and prod4 are objects of classes Computer and Keyboard respectively. The interesting thing is
  the mixing of a trait ApplyDiscount to the instances created.
  val prod3 = new Computer with ApplyDiscount
  val prod4 = new KeyBoard with ApplyDiscount
 
  Here the call super.put(x*0.8) delegates the call to the trait/class towards its left.
 
  abstract override def put(x:Double) = super.put(x*0.8)
 
  The discount get applied to the object mixing with this trait.

//STACKING TRAITS
4) prod5 and prod6 are objects that mix with more than one trait namely ApplyDiscount and AddTax.
  At first the AddTax trait is applied and delegated to ApplyDiscount and finally to the class mixing these traits.
 val prod5 = new Computer with ApplyDiscount with AddTax
 val prod6 = new KeyBoard with ApplyDiscount with AddTax

 The flow:
 super.put(x-x*0.07)->super.put(x*0.8)->put(x)

Thursday, June 20, 2013

Scala => 1) function literal, 2) implicit conversion, 3) Operator overloading 4) Traits discussed

import java.io.PrintWriter

trait Destination { 
 val str:String
 def sendMess
}
class Towers(f:(String)=>Unit, valToSend:String) extends Destination {  
  val str = valToSend  
   def sendMess {  
  f(str) 
}
}

class Churchill(f:(String)=>Unit, valToSend:String) extends Destination {  
   val str = valToSend  
   def sendMess {  
      f(str)  
 }
}

class MyClass(val str:String)

class Sender{
var dests:List[Destination] = List() 
 def +(x:Destination) = dests::=x 
 def sendMessages = for(dest<-dests) dest.sendMess
}
object MyObj { 

def myTest { 
 import MyConversions._  
  val dest1 = new Towers(printContent, "Hi this is Towers")  
  val dest2 = new Churchill(printContent, "Hi this is Churchill")  
  var send = new Sender  
  send+dest1  
  send+dest2  
  send.sendMessages  
  var send1 = new Sender  
  val dest3 = new Towers(printContent, new MyClass("This is implicit Towers message 1"))
  val dest4 = new Churchill(printContent, new MyClass("This is implicit Churchill message 1"))    send1+dest3  
   send1+dest4  
   send1.sendMessages  
} 
def printContent(x:String):Unit= {  
     val pw = new PrintWriter("testObserver.txt", "UTF-8")
     pw.write(x) pw.flush 
   }
}
object MyConversions { 
   implicit def conToStr(x:MyClass):String = x.str
}
MyObj.myTest


EXPLANATION:
The example I tried to show here is the Observer core design pattern. 

Observer Pattern: In this pattern there will be a single source point but multiple destination points. Each destination point is unaware of one another. Therefore they are decoupled and hence addition of new destinations can be done and therefore it enhances maintainability without much rework.
Examples of Observer patterns are
1) Cellphone tower: As soon as the tower bandwidth is up, it notifies all the cellphones within its range.
2) Logs in a web application: We can have our log statement go multiple locations (Application logs, System logs etc..)


The trait Destination encompasses the abstract fields/methods that the concrete destinations implement.
In this example the destinations are 1) Towers & 2) Churchill. These were the two apartments in Minneapolis where I stayed. Each of these classes has a sendMess method which does some work.
There are two parameters of this method. One is a function literal and the other is a String. 

A function literal is closely similar to anonymous classes in java.
Java Anonymous Class: When we do not want to have a sub-class , when we want to have a inline class implementation , when we want to reduce verbosity by writing smaller classes in separate files,  then we can use an anonymous class.

Eg: Consider an Interface Product which has a single method getName() which returns a String. Consider a client which is trying to use a concrete implementation of Product but does not like it having sub-classed for the above mentioned reasons.
public interface Product{
      public String getName();
}
// Method which needs a product type parameter.
public void myMethod(Product prod){
     
}

//Client code which calls the myMethod method using Anonymous Functions
myMethod(new Product{
      @Override // Just to make sure we are overriding the method indeed.
      public String getName() {
              return "Anonymous Product" ;
     }
});

// Client code which calls the myMethod method normally (without anonymous classes)
public class ProductImpl extends Product {
      @Override
       public String getName() {
                return "Anonymous Product";
       }
}
Product prod = new ProductImpl();
myMethod(prod);

The above code increases verbosity and since the class implementation has just one small method , it need not be sub-classed.

Function Literal: On the other hand, a function literal in Scala need not have an enclosing wrapper (unlike anonymous classes in java ) to be able to survive. It is of the form func:(T,M)=>K. Here the function literal's reference is 'func' which takes parameters T & M as input and returns a value of type K. Here the part towards the right side of "=>" is its body and the part towards the left of "=>" are its input parameters. The function's parameters and the body have to be supplied by the client calling the function literal. The function literal can be easily passed as parameters to other functions, as return values, as variable types and even as Type Parameters for eg: MyClass[f:(Int,Float):Boolean] is a class with a Type parameter f:(Int,Float):Boolean. Though we have type parameters in java of the form MyClass<T> , T cannot be a function literal as the Java compiler does not allow that.
As part of Java 8 , there is a Project called Project Lambda which is contemplating on bringing function literals into java and the syntax proposed is something like this.... f:(int, float) <- Boolean.

Coming back to our code...

In our example the function literal f:(String)=>Unit takes a String as an input and returns nothing (Unit). Unit represent the return type of a function which returns nothing. This function literal in our code holds the implementation of the sendMess method of the classes implementing the Destination trait. The implementation of the function literal is supplied by the method printContent. This method will give the concrete implementation of what has to be done when the sendMess method is called from each of the concrete implementations of the Destination trait.
The function literal just creates a PrintWriter from the java.io package and writes the string to the writer.

def printContent(x:String):Unit= {
val pw = new PrintWriter("testObserver.txt", "UTF-8")
pw.write(x)
pw.flush
}
}
By sending the implementation (as a function literal) we are removing the duplication of code within each of the classes which extends Destination. Therefore even if another 10 new destination implementations come, the code need not change and can be easily integrated with the existing code.

Implicit conversions: The variables dest3 and dest4 should ideally parameters 1) F:(String)=>Unit and 2) String. But, these variables take 1) F:(String)=>Unit and 2) MyClass. Therefore the compiler should throw an error. But it does not happen. This is where the implicit conversions come into picture.
The moment when the compiler realizes that something wrong w..r.t the parameters has happened or it sees any compilation errors, it does not give it up and throw an error but checks if there have been any implicit definitions have been made by the user or in the Predef object.

Here in our case when the compiler comes across the code..

val dest3 = new Towers(printContent, new MyClass("This is implicit Towers message 1")).

The part in red is read as a compilation error, then the compiler checks if the user has imported any implicit conversions.
The implicit conversion definition is defined in the MyConversions object with the name conToStr . The name does not matter here but the keyword implicit matters everything. This keyword tells the compiler that there is a conversion that the user is providing for an object of type MyClass. This conversion definition converts this MyClass into a String. This conversion makes the compiler successful in parsing the variable declaration dest3 and dest4. The implicit definition conToStr is defined as follows..


object MyConversions {
implicit def conToStr(x:MyClass):String = x.str
}

The definition just takes an object of MyClass and returns a String and remember to import this object for the conversion to apply.
import MyConversions._

Operator Overloading: The operator + is overloaded by the users own implementation. This is similar to adding an object to another.i.e. obj1.add(obj2) is simplified to obj1+obj2. This code adds the obj2 to obj1. The custom definition of the operator "+" is give just the same way any other function is defined.
for e.g: def methodName(Parameters) = def +(x:Destination): Unit
Here the method name is replaced with "+" and it can be used as a+b instead of a .+(b) which is the underhood implemtation which Scala provides.


CODE FLOW EXPLANATION:
1) A trait (named Destination) which abstracts the functions a destination provides is created. Provide concrete implementations to this trait with Names Churchill and Towers. These are the places where the message has to be delivered.
2) The concrete classes implement the sendMess method by calling the function literal f.
3) Create a Sender class which collects all the destinations which the user wants to send his message to. This class defines a "+" method which adds new destinations supplied by the client calling it. The method sendMessages iterates through the Destinations and calls the sendMess method on each of the destination.
4) Create MyConversions object and import it as import MyConversions._
5) The client code MyObj has a method myTest which instantiates the Churchill and Towers classes, adds them to the Sender object and calls the sendMessages on the Sender object. This will eventually call the function literal f:(String)=>Unit on each of the concrete Destination classes and the message will be delivered by writing the message to a file with the name testObserver.txt.

Advantages:
1) Enhance re usability through traits.
2) Function literals enhance robustness and make code less verbose.
3) Implicit conversions make integration with legacy java libraries easy.
4) Operator overloading makes using operators with their own syntax but custom defined implementation.









Friday, June 14, 2013

Simple custom Stack[Type] implementation in Scala.

trait MyStack[T] {
 def push(x:T):MyStack[T]
 def pop:MyStack[T]
 def isEmpty:Boolean
 def top:T
 def length:Int
}

object MyStack {

 def apply[M](xs:M*):MyStack[M] = new MyStackImpl[M](xs.toList)

 class MyStackImpl[M](var xs:List[M]) extends MyStack[M] {

  def push(pu:M):MyStackImpl[M] = new MyStackImpl[M](pu::xs)

  def pop:MyStackImpl[M] = new MyStackImpl(xs.tail)

  def top:M = xs.head

  def isEmpty:Boolean = if(xs.length==0) true else false
                def head:M = xs.head

  def length:Int = xs.length
 }
}

def myTest {
val stack1 = MyStack(1,2,3,4,5) // This is similar to Mystack apply (1,2,3,4,5)
println(stack1.top) // Prints the top most element of the stack
val stack2 = stack1.push(5)
println(stack2.top) // After 5 is added to the top, this statement prints 5 as the top element
println(stack2.pop.top) // This statement pops the top element (5) and prints the top element (1)
println(stack2.pop.pop.pop.pop.pop.pop.length) // This will print 0 since all the elements of                          the stack are popped.
}
myTest


//OUTPUT
1
5
1
0


Explanation:
1) Create a Typed trait (MyStack[T])which can be used to create Stacks that can accommodate any types.
2) The companion object is MyStack (with the same name as that of the trait). This becomes a  companion object of all the concrete classes which are mixed with the trait MyStack. This will ensure the object has access to the private members (if any, in this case we don't have private members) of the concrete classes.
3) The apply method of the object has to be implemented. The input parameter is a sequence of
elements of type M. The sequence will be converted into a List (using seq.toList method) for processing.
The apply method allows us to use the class as a Factory. for eg: MyStack(1,2,3,4,5) which has the implementation MyStack.apply(1,2,3,4,5) under the hood.
4) This class MyStackImpl  is the concrete implementation of the custom Stack trait. The constructor is a list
which was created using the Sequence element from the input parameter of the apply method present
in this object.
5) The push method of the MyStackImpl object adds an element of type M at the top of the stack and returns a new MyStackImpl object with the newly added element at the top
6) The pop method of the MyStackImpl  removes(pops) the top most element from the stack and returns another MyStackImpl object without the popped element.
7) The top method returns the top most element from the stack.
8) The isEmpty methods returns true if there are no elements in the stack and false when at least one element is present.
9) This length function returns the length of the stack.




Create your own 'typed' Map implementation in Scala


trait MyMap[K,V] {
 def get(x:K):V
 def +(x:K, y:V):MyMap[K,V]
 def isEmpty:Boolean
 def keys:List[K]
 def values:List[V]
}
object MyMap{
 def apply[K,V](x:Tuple2[K,V]*):MyMap[K,V] = new MyMapImpl[K,V](x.toList)
 class MyMapImpl[T,M](var myMap:List[Tuple2[T,M]]) extends MyMap[T,M] {
  def get(x:T):M = {
   for((key,value)<-myMap) {
    if(key==x)
    return value
   }
   throw new Exception("Value not found!!!")
  }
  def +(x:T,y:M):MyMapImpl[T,M] = {
   for((key,value)<-myMap){
    if(key==x)
    throw new Exception("Key value already exists")
   }
   myMap::=Tuple2(x,y)
   new MyMapImpl[T,M](myMap)
  }
  def isEmpty:Boolean = if (myMap.length==0) true else false
  def keys:List[T] = for((key,value)<-myMap) yield {key}
  def values:List[M] = for((key,value)<-myMap) yield {value}
 }
}
def myTest {
 val myMap1 = MyMap((1,"Sandeep"),(2,"Praveen"),(3,"Vikas"),(4,"Suresh"))
 println(myMap1.get(3)) // Getting the value with key 3
 println(myMap1.keys) // Displaying a list of all keys
 println(myMap1.values) // Displaying a list of all values

 val myMap2 = myMap1+(5,"Pranay") // Add a key value pair to our custom Map(MyMap)

 println(myMap2.keys) // Displaying the list of keys of our map including '5' added in previous line
 println(myMap2.values)
}
myTest



//Output
Vikas
List(1, 2, 3, 4)
List(Sandeep, Praveen, Vikas, Suresh)
true
List(5, 1, 2, 3, 4)
List(Pranay, Sandeep, Praveen, Vikas, Suresh)


Explanation:

We have a predefined Map definition under the scala.predef object. Using similar methods present in the Map object we can come up with our own definition of the Map.

The underlying data structure we will be using is a List, therefore the results will all be in the form of lists.

1) Define a trait with a preferred name (say MyMap) and define all the abstract methods which your custom map should expose. Make sure your map is typed so that we can create a map of any object type say MyMap[Any,Any].
2) Define an object (with the same name MyMap), this object is the companion object of all the concrete classes which mixes in with the trait MyMap.
3) Override the apply function in the object . The input parameters of the apply function will be a sequence of Tuple2 's. x:Tuple2[K,V]* indicates patterns of the form (a,b),(c,d)(e,f) (where every alphabet represents any object in scala, Any)
4) Write a class inside the MyMap object which will be a concrete implementation of the trait MyMap. Lets say the concrete class is MyMapImpl which takes arguments of type List[Tuple2[K,V]] which means it a list of Tuple2's of type[K,V] which are key & value pairs. We should make sure we represent the variable of this type is a var and not a val.
5) Implement the methods in the MapTrait. One of the method here needs special attention. The "+" operator is now an overloaded method which is used to add a mapping entry into the custom map. This operator takes the Tuple as an input and return an object of the for MyMapImpl which also includes the newly added mapping.

6) Once the map is ready, write a test method (say myTest) and test the functionality of the methods you just implemented.