Showing posts with label Functional programming. Show all posts
Showing posts with label Functional programming. Show all posts

Sunday, January 27, 2013

Scala pattern matching: A Case for new thinking?

A new thinking?
The 16th President of the United States. Abraham Lincoln once said: "As our case is new we must think and act anew".   In software engineering things probably aren't as dramatic as civil wars and abolishing slavery but we have interesting logical concepts concerning "case". In Java the case statement provides for some limited conditional branching.  In Scala, it is possible to construct some very sophisticated pattern matching logic using the case / match construct which doesn't just bring new possibilities but a new type of thinking to realise new possibilities.

Let's start with a classical 1st year Computer Science homework assignment: a fibonacci series that doesn't start with 0, 1 but that starts with 1, 1.   So the series will look like: 1, 1, 2, 3, 5, 8, 13, ... every number is the sum of the previous two.

In Java, we could do:
public int fibonacci(int i) {
    if (i < 0) 
        return 0;
    switch(i) {
        case 0:
            return 1;
        case 1:
            return 1;
        default:
            return fibonacci(i-1) + fibonacci(i - 2);
    }
}     
All straight forward. If 0 is passed in it counts as the first element in the series so 1 should be returned. Note: to add some more spice to the party and make things a little bit more interesting I added a little bit of logic to return 0 if a negative number is passed in to our fibonacci method.

In Scala to achieve the same behaviour we would do:
def fibonacci(in: Int): Int = {
  in match {
    case n if n <= 0 => 0
    case 0 | 1 => 1
    case n => fibonacci(n - 1) + fibonacci(n- 2)
  }
}
Key points:
  • The return type of the recursive method fibonacci is an Int. Recursive methods must explictly specify the return type (see: Odersky - Programming in Scala - Chapter 2).
  • It is possible to test for multiple values on the one line using the | notation. I do this to return a 1 for both 0 and 1 on line 4 of the example.
  • There is no need for multiple return statements. In Java you must use multiple return statements or multiple break statements.
  • Pattern matching is an expression which always returns something.
  • In this example, I employ a guard to check for a negative number and if it a number is negative zero is returned.
  • In Scala it is also possible to check across different types. It is also possible to use the wildcard _ notation. We didn't use either in the fibonacci, but just to illustrate these features...
    def multitypes(in: Any): String = in match {
      case i:Int => "You are an int!"
      case "Alex" => "You must be Alex"
      case s:String => "I don't know who you are but I know you are a String"
      case _ => "I haven't a clue who you are"
    }
    
Pattern matching can be used with Scala Maps to useful effect.  Suppose we have a Map to capture who we think should be playing in each position of the Lions backline for the Lions series in Austrailia.  The keys of the map will be the position in the back line and the corresponding value will be the player who we think should be playing there.  To represent a Rugby player we use a case class. Now now you Java Heads, think of the case class as an immutable POJO written in extremely concise way - they can be mutable too but for now think immutable.
case class RugbyPlayer(name: String, country: String);
val robKearney = RugbyPlayer("Rob Kearney", "Ireland");
val georgeNorth = RugbyPlayer("George North", "Wales");
val brianODriscol = RugbyPlayer("Brian O'Driscol", "Ireland");
val jonnySexton = RugbyPlayer("Jonny Sexton", "Ireland");  
val benYoungs = RugbyPlayer("Ben Youngs", "England");
    
// build a map
val lionsPlayers = Map("FullBack" -> robKearney, "RightWing" -> georgeNorth, 
      "OutsideCentre" -> brianODriscol, "Outhalf" -> jonnySexton, "Scrumhalf" -> benYoungs);
    
// Note: Unlike Java HashMaps Scala Maps can return nulls. This achieved by returing
// an Option which can either be Some or None. 
    
// So, if we ask for something that exists in the Map like below
println(lionsPlayers.get("Outhalf"));  
// Outputs: Some(RugbyPlayer(Jonny Sexton,Ireland))
    
// If we ask for something that is not in the Map yet like below
println(lionsPlayers.get("InsideCentre"));
// Outputs: None
In this example we have players for every position except inside centre - which we can't make up our mind about.  Scala Maps are allowed to store nulls as values.  Now in our case we don't actually store a null for inside center. So, instead of null being returned for inside centre (as what would happen if we were using a Java HashMap), the type None is returned.

For the other positions in the back line, we have matching values and the type Some is returned which wraps around the corresponding RugbyPlayer. (Note: both Some and None extend from Option).

We can write a function which pattern matches on the returned value from the HashMap and returns us something a little more user friendly.
def show(x: Option[RugbyPlayer]) = x match {
  case Some(rugbyPlayerExt) => rugbyPlayerExt.name  // If a rugby player is matched return its name
  case None => "Not decided yet ?" // 
}
println(show(lionsPlayers.get("Outhalf")))  // outputs: Jonny Sexton
println(show(lionsPlayers.get("InsideCentre"))) // Outputs: Not decided yet
This example doesn't just illustrate pattern matching but another concept known as extraction. The rugby player when matched is extracted and assigned to the rugbyPlayerExt.  We can then return the value of the rugby player's name by getting it from rugbyPlayerExt.  In fact, we can also add a guard and change around some logic. Suppose we had a biased journalist (Stephen Jones) who didn't want any Irish players in the team. He could implement his own biased function to check for Irish players
def biasedShow(x: Option[RugbyPlayer]) = x match {
  case Some(rugbyPlayerExt) if rugbyPlayerExt.country == "Ireland" => 
     rugbyPlayerExt.name + ", don't pick him."
  case Some(rugbyPlayerExt) => rugbyPlayerExt.name
  case None => "Not decided yet ?"
}
println(biasedShow(lionsPlayers.get("Outhalf"))) // Outputs Jonny... don't pick him
println(biasedShow(lionsPlayers.get("Scrumhalf"))) // Outputs Ben Youngs

Pattern matching Collections

Scala also provides some powerful pattern matching features for Collections. Here's a trivial exampe for getting the length of a list.
def length[A](list : List[A]) : Int = list match {
  case _ :: tail => 1 + length(tail)
  case Nil => 0
}
And suppose we want to parse arguments from a tuple...
  def parseArgument(arg : String, value: Any) = (arg, value) match {
    case ("-l", lang) => setLanguage(lang)  
    case ("-o" | "--optim", n : Int) if ((0 < n) && (n <= 3)) => setOptimizationLevel(n)
    case ("-h" | "--help", null) => displayHelp()
    case bad => badArgument(bad)
  }

Single Parameter functions

Consider a list of numbers from 1 to 10. The filter method takes a single parameter function that returns true or false. The single parameter function can be applied for every element in the list and will return true or false for every element. The elements that return true will be filtered in; the elements that return false will be filtered out of the resultant list.
scala> val myList = List(1,2,3,4,5,6,7,8,9,10)
myList: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> myList.filter(x => x % 2 ==1)
res13: List[Int] = List(1, 3, 5, 7, 9)
Now now now, listen up and remember this. A pattern can be passed to any method that takes a single parameter function. Instead of passing a single parameter function which always returned true or false we could have used a pattern which always returns true or false.
scala> myList.filter {
     |     case i: Int => i % 2 == 1   // odd number will return false
     |     case _ => false             // anything else will return false
     | }
res14: List[Int] = List(1, 3, 5, 7, 9)

Use it later?

Scala compiles patterns to a PartialFunction.  This means that not only can Scala pattern expressions be passed to other functions but they can also be stored for later use.
scala> val patternToUseLater = : PartialFunction[String, String] = {
     |   case "Dublin" => "Ireland"
     |   case _ => "Unknown"
      }
What this example is saying is patternToUseLater is a partial function that takes a string and returns a string.  The last statemeent in a function is returned by default and because the case expression is a partial function it will returned as a partial function and assigned to pattenrToUseLater which of course can use it later.

Finally, Johnny Sexton is a phenomenal Rugby player and it is a shame to hear he is leaving Leinster. Obviously, with Sexton's busy schedule we can't be sure if Johnny is reading this blog but if he is, Johnny sorry to see you go we wish you all the best and hopefully will see you back one day in the Blue Jersey.

Sunday, January 13, 2013

Scala: Do you partially understand this?

Nearly everyone who learns Scala can get confused over the word partial used in the contexts:
  • Partial functions
  • Partially applied functions 
Let's look at both.

Partially applied functions

Scala gets its functional ideas from classical languages such as Haskell (Haskell 1.0 appeared in same year as Depeche Mode's Enjoy the Silence and Dee Lite's Groove is in the Heart in 1990).  In functional languages a function that takes two parameters that returns one parameter can be expressed as a function which takes one of the input parameters and returns a function that takes the other input parameter and returns the same output parameter.

f(x1, x2) = y
f(x1) = f(x2) = y

A cheesey analogy would be to time travel back to 1990 and find yourself a juxebox. Put money in for two selections and select Depeche Mode first and Dee Lite second, walk away and throw a few shapes as they  are played one after the other.  Or, put in your money for two selections select Depeche Mode and then don't make another selection.  Don't walk away just yet.  The well engineered Juxebox should prompt you for another selection (give you another function) and then you can select Dee Lite (pass in the second parameter). So, the end output in both cases is the same music in the same order.

In Scala, when only some parameters are passed to a function to make another function it is said to be a partial application of that function.

So consider the function:
def minus(a: Int, b: Int) = "answer=" + (a-b)
Now, let's partially apply this function by passing in some parameters and making another function.
val minus50 = (a: Int) => minus(a, 50);
In this case minus50 is a partial application of minus.
We can do:
minus50(57); // outputs 7.
Note: we can also partially apply using the _ notation and a save ourselves a little bit of finger typing.
val minus50 = minus(_:Int, 50);

Partial functions

A partial function is a function that is valid for only a subset of values of those types you might pass into it. For example, Consider the mathematical function where x is set of all number from 1  to 100: 

f(x) =  x + 5;

A function is said to be partial if the function is only applied to a subset in set of element of x.
So if we only want to define the function

f(x) = x + 5

for the numbers 1,2,3,4,5,6,7 but not 8,9,10, ... - we define a partial function.
f(x')=x+5
where x' = {1,2,3,4,5,6,7}

In Scala, a PartialFunction inherits from Function and adds two interesting methods:
  • isDefinedAt - this allows us to check if a value is defined for the partial function.
  • orElse - this allows partial functions to be chained. So if a value is not defined for a function it can be passed to another function. This is similar to the GoF Chain of Responsibility pattern.
Ok so open up a Scala REPL and create the following partial function which will add 5 to an integer as long as the integer is less than 7.
val add5Partial : PartialFunction[Int, Int] = {
  case d if (d > 0) && (d <= 7) => d + 5;
}
When you try this for a value less than or equal to 7, you will see the result no problem
scala > add5Partial(6);
res1: 11
When you try it for a value greater than 7 you don't get a nice clean answer.
scala> myPartial(42);
scala.MatchError: 42 (of class java.lang.Integer)
        at $anonfun$1.apply$mcII$sp(:7)
        at .(:9)
        at .()
        at .(:11)
        at .()
        at $print()
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
        at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
        at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
        at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
        at java.lang.Thread.run(Thread.java:722)

The use of isDefinedAt() should now be becoming apparent. In this case, we could do:
 add5Partial.isDefinedAt(4)
res3: Boolean = true

scala> add5Partial.isDefinedAt(42)
res4: Boolean = false
Ok so what about orElse? Well let's define another partial function which deals with numbers greater than 7 and less than 100. In such cases, lets' just add 4.
val add4Partial : PartialFunction[Int, Int] = {
  case d if (d > 7) && (d <= 100) => d + 5;
}
Now we can just do:
scala> val addPartial = add5Partial orElse add4Partial;
addPartial : PartialFunction[Int,Int] = <function1>
scala> addPartial(42);
res6: Int = 46
Ok, let's see how all this could be implemented in Java using Chain of Responsibility pattern.  Firstly, let's define a handler interface and an add5 and add4 implementation which will implement it.

//Handler
public interface AdditionHandler {
    //reference to the next handler in the chain
    public void setNext(AdditionHandler handler);
    //handle request
    public void handleRequest(int number);
}

public class Add5Handler implements AdditionHandler {
    private AdditionHandler nextAdditionHandler = null;
    public void setNext(AdditionHandler hander)  {
        this.nextAdditionHandler = handler;
    } 

    public int handleRequest(int number) {
         if ((number > 0) && (number <= 7)) {
             return number + 5;
         } else {
             return nextAdditionHandler.handleRequest(number);
         }
    }
}

public class Add4Handler implements AdditionHandler {
    private AdditionHandler nextAdditionHandler = null;
    public void setNext(AdditionHandler hander)  {
        this.nextAdditionHandler = handler;
    } 

    public int handleRequest(int number) {
         if ((number > 7) && (number <= 100)) {
             return number + 4;
         } else {
             return nextAdditionHandler.handleRequest(number);
         }
    }    
}
Now, let's create a class which will link the handlers.
public class AdditionProcessor {
   private AdditionHandler prevHandler;
   public void addHandler(AdditionHandler handler){
       if(prevHandler != null) {
           prevHandler.setNext(handler);
       }
       prevHandler = handler;
   } 
}
And of a course a client which actually invokes the functionality:
public class AdditionClient {
    private AdditionProcessor processor;
    public AdditionClient(){
        createProcessor();
    }

    private void createProcessor() {
        processor = new AdditionProcessor();
        processor.addHandler(new Add5Handler());
        processor.addHandler(new Add4Handler());
    }

    public void addRule(AdditionHandler handler) {
        processor.addHandler(handler);
    }

    public void requestReceived(int value){
        System.out.println("value=" + processor.handleRequest(value));  
    }

    public static void main(String[] args) {
        AdditionClient client = new AdditionClient();

    }
}
So Scala has some clear advantages here.  Or course, people will say 'ah but in Java you just just do...'
public int addFunction(int value) {
    if ((value > 0) && (value <= 7)) {
       return value + 5;
    } else if ((value > 7) && (value < 100)) {
       return value + 4;
    } else {
      // ...
    }
}
And yes for this specific case, this will work. But what if your functions/ commands become more complex. Are you go to hang around in if / else land? Probably not. 'Til the next time, take care of yourselves.

Sunday, January 6, 2013

Scala function literals

Functions are an important part of the Scala language. Scala Functions can have a parameter list and can also have a return type. So the first confusing thing is what's the difference between a function and a method? Well the difference is a method is just a type of function that belongs to a class, a trait or a singleton object.
So what's cool about functions in scala? Well you can define functions inside functions (which are called local functions) and you can also have anonymous functions which can be passed to and returned from other functions. This post is about those anonymous functions which are referred to as function literals.
As stated, one of the cool things about function literals is that you can pass them to other functions. For example, consider snippet below where we pass a function to a filter function for a List.
List(1,2,3,4,5).filter((x: Int)=> x > 3)
In this case, the function literal is (x: Int)=> x > 3 This will output: resX: List[Int] = List(4, 5). => called "right arrow" means convert the thing on the left to the thing on the right. The function literal in this example is just one simple statement (that's what they usually are), but it is possible for function literals to have multiple statements in a traditional function body surrounded by {}. For example, we could say:
List(1,2,3,4,5).filter((x: Int)=>{
  println("x="+ x);
  x > 3;})
which gives:
x=1
x=2
x=3
x=4
x=5
resX: List[Int] = List(4, 5)
Now one of the key features of Scala is to be able to get more done with less code. So with that mindset, let's see how we can shorten our original function literal. Firstly, we can remove the parameter type.
List(1,2,3,4,5).filter((x)=> x > 3)
This technique is called target typing. The target use of the expression in this case, what is going to filter is allowed to determine the type of the x parameter. We can further reduce the strain on our fingers by removing the parentheses. This is because the parentheses were only there to show what was been referred to as Int in the parameter typing. But now the typing is inferred the brackets are superflous and can be removed.
List(1,2,3,4,5).filter(x => x > 3)
Shorten it even more? yeah sure... We can use the placeholder underscore syntax.
List(1,2,3,4,5).filter(_ > 3)
Underscores have different meanings in Scala depending on the context they are used. In this case, if you are old enough think back to the cheesey game show blankety blank.
This gameshow consisted of of sentences with blanks in them and the contestants had to make suggestions for what went into the blank. In this example, the filter function fills in the blanks with the values in the Lists it is being invoked on. So the filter function is the blankety blank contestant and the List (1,2,3,4,5) are what the filter function uses to fill the blank in.
So now our code is really neat and short. In Java to achieve the same, it would be:
Iterator<Integer> it = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5)).iterator();
while( it.hasNext() ) {
    Integer myInt = it.next();
    if(myInt > 3) it.remove();
}
So, here we can see where Scala make code shorted and development time quicker. Till the next time!