Tag Archives: pattern matching

Matching a combination of class and trait in Scala

While doing some development with Scala I discovered that it is possible to match combinations of a class and traits. It might seem obvious if you already know it, but I didn’t.

What happened is that I needed something like matching that kind of combination… and this speaks to something about Scala that I love: it becomes intuitive after a while. So how did I find that such matching is possible? I simply tried… =)

This is what this feature looks like:

msg match {
  case x: X with Z => println("matching combination!")
}

In this case, X would be a class, and Z a trait. The case x will be triggered only if msg is an instance of class X and mixes in trait Z. With this, we make sure to have access to all members both from the class and from the trait, while being really type safe about the matching. No unsupported combinations will pass through, and no need for castings, like would be necessary in Java.

Lets try a dummy example. Imagine we have a Superman class, and two traits: BlueCape and RedCape, like the following code:

class Superman(val realname: String)
trait BlueCape
trait RedCape

Now, we want to match on a Superman instance, but we want to know if it is fake or not. Finally, we also want to print the guy’s name, which means we need access to the realname field. This is how you could do that:

def whichSuperman(superman: AnyRef) = superman match {
  case s: Superman with RedCape => println("real superman: " + s.realname)
  case f: Superman with BlueCape => println("fake superman: " + f.realname)
}

Flexible and type safe! And if the traits had any field, we would be able to access them as well. Quick sample test code:

val mys = new Superman("clark") with RedCape
val myf = new Superman("clurk") with BlueCape

whichSuperman(mys)
whichSuperman(myf)

The part that matches the class is not very useful in this example, since this could be defined in the function parameter, but it was in my local scenario, where we are using actors and the messages can be AnyRef.

If you want to know a bit more about pattern matching, I wrote about it a while ago here. I also described how to match a range of numbers here.


Scala Problem Number Five

From the Scala 99 Problems, the problem number five goes like this:

P05 (*) Reverse a list.
Example:

scala> reverse(List(1, 1, 2, 3, 5, 8))
res0: List[Int] = List(8, 5, 3, 2, 1, 1)

Starting with the obvious solution, using the API:

val list = List(1, 2, 3, 4)
list.reverse

Yes, the List API has a reverse function. Pretty handy =)

How about being more creative now? Like this:

def myReverse[A](list: List[A]): List[A] = list match {
  case head :: tail => myReverse(tail) :+ head
  case Nil => Nil
}

With pattern matching and recursion, the solution is pretty simple. We basically decompose the list, and rebuild it in the opposite order. The code is simple, but it can take a while to understand if you are not used to recursion. The pattern matching part shows how nicely we can decompose Lists in scala =)

Lets try a different solution now:

def myReverse[A](list: List[A]): List[A] = {
  var reversedList = List[A]()
  list.foreach(item => reversedList = item +: reversedList)
  reversedList
}

Here we take a more ‘traditional’ approach – its closer to what we would do in Java, but still more compact and readable. First we create a buffer list, and add each element of the original list to the beginning of the buffer. Finally, we return the reversed list.

You can find the original solution to the problem here. As always, I learned something more after reading the original solution – I always write my solution before reading that. What I found is that it is also possible to solve the problem in a pure functional way, with foldLeft (copied from the original solution):

def reverseFunctional[A](ls: List[A]): List[A] =
    ls.foldLeft(List[A]()) { (r, h) => h :: r }

This solution is probably the most difficult to get at first, but the best after you get used to this kind of ‘extreme’ functional stuff. Nice =)


Matching a range of numbers in Scala

Hi everybody!

Yesterday I did a presentation about Scala at Globalcode. It was very nice, thank you all who attended!

Now, one of the things I liked the most was the final part when people started making questions. I must admit I didn’t have answers to some of them, and this post is about one of those.

The question was something like: “can I pattern match against a range of numbers, like, say, 1 to 10?”

The answer is yes, although with a little more code than I thought necessary – yet, the solution is simple. First, if we want to match a simple number, we could write something like this:

myNumber match {
  case 10 => println("a ten")
  case num: Int => println("a number")
  case _ => println("something else")
}

In terms of matching numbers, we have two cases here. In one of them, we match directly a ’10′. In the other, we match any number. But how do we match a range of numbers? By adding something extra in the ‘any number’ case:

myNumber match {
  case 10 => println("a ten")
  case num if 0 until 100 contains num => println("a number between 0 and 100")
  case _ => println("something else")
}

This ‘something extra’ is called a ‘guard’. Guards allow us to add more verifications to values we match. With this, we can have any kind of restriction in any matched value. Also, we could have a ‘case’ for numbers between 0 and 100, and another one for any other number, like this:

myNumber match {
  case 10 => println("a ten")
  case num if 0 until 100 contains num => println("a number between 0 and 100")
  case num: Int => println("a number")
  case _ => println("something else")
}

Finally, please mind the order of the cases. Notice how we go from the more specific numbers, to the broader matching. This is not optional. you cannot put the broader case before the other ones – the code won’t even compile. In summary, this won’t work:

myNumber match {
  case num: Int => println("a number")
  case 10 => println("a ten")
  case num if 0 until 100 contains num => println("a number between 0 and 100")
  case _ => println("something else")
}

Now lets talks about how this work. Like a lot of things in Scala, ’0 until 100′ is not a special construct. It is implemented as library – which means you could have implemented this yourself. The steps that the scala compiler has to take to make this magic happen is something similar to the following:

  • 0 is an Int, so the compiler tries to find an ‘until’ method in the Int class, but it doesn’t exist;
  • the compiler finds out that the ‘until’ method exists in the ‘RichInt’ class;
  • it would be perfect if 0 was a RichInt… so the compiler now searches for a way to transform an Int in a RichInt;
  • luckily, it finds this: ‘implicit def intWrapper (x: Int) : RichInt’ in the Predef object;
  • 0 is then wrapped in a RichInt, and the compiler calls its until method, with ’100′ as the parameter;
  • the ‘until’ call results in a Range object and the compiler calls its ‘contains’ method, passing ‘num’ as the parameter;
  • the result of ‘contains’ is a boolean, which will decide if the number matches or not which what we want.

That’s quite a lot of stuff happening, even though there is nothing too complex in there. To close, one more last bit of information. Predef is an object that contains a lot of helper implicit methods, which are in the classpath of any scala application by default. Very handy.

I would like to thank Henrique Prage, who was in the Scala presentation, and sent me this link this morning: http://stackoverflow.com/questions/1346127/can-a-range-be-matched-in-scala – it really helped me find out quickly the answer to this question =)


A Scala script for processing files

This time, we will approach Scala through a different angle: that of a script file. If you see Scala solely as a ‘normal’ programming language, this should demonstrate that Scala offers more possibilities than you knew.

The code I’ll show bellow was not created only for this post. It was actually used to solve a small problem in a project. This means that, even if it is not as nice and beautiful as it could be, it did the job well.

First. lets describe what we are trying to do here. We had several text files that needed a certain pattern to be found and replaced by something else. Of course, this job could be done manually… but with tens of files, it would take a while… and would be very error prone. Another option would be to write a shell script to solve the problem. But we don’t have anyone in the team that are really good shell scripters.

So I took the opportunity to solve the problem in Scala, with a small script, that would scan all the files, one by one, search for the pattern and replace it with the new value.

To write a Scala script, you just type the commands directly in the script file, instead of putting them inside a class. So the code consist basically of some commands, followed by some function definitions that are used by these commands. Here is the source code, and some explanation after it:

import java.io._
import scala.util.matching.Regex
import Regex._

// entry point for the script execution
processDir(new File("."))

def processDir(dir: File) {
 for (f <- dir.listFiles) {
  if (f.isDirectory) {
   processDir(f)
  } else {
   val extension = f.getName.lastIndexOf('.') match {
    case -1 => None
    case x:Int => new Some(f.getName.substring(x + 1).toLowerCase)
   }

   if (List(Some("java"), Some("sql")) contains extension) {
    processFile(f)
   }
  }
 }
}

def processFile(file: File) {
 val fileContents = getFileContents(file)
 if (fileContents != null) {
  val regex = "\\\\u[0-9a-fA-F]{4}".r
  val newFileContents = regex.replaceAllIn(fileContents, m => replaceUnicode(m.matched))

  if (fileContents != newFileContents) {
   val newFile = new File(file.getName + ".conv")
   val writer = new BufferedWriter(new FileWriter(newFile))

   writer.write(newFileContents, 0, newFileContents.length)
   writer.close

   file.delete
   newFile.renameTo(file)
  }
 }
}

def getFileContents(file: File) = {
 val reader = new BufferedReader(new FileReader(file))

 var line = reader.readLine
 var content = line
 while (line != null) {
  line = reader.readLine
  if (line != null) {
   content += '\n' + line
  }
 }

 reader.close
 content
}

def replaceUnicode(s: String) = {
 val unicode = s.substring(2)
 val unicodeChars = new Array[Char](1)
 unicodeChars(0) = Integer.parseInt(unicode, 16).asInstanceOf[Char]

 new String(unicodeChars)
}

First interesting thing to noticing is that we are leveraging a lot of already existent Java API knowledge – mainly File stuff from java.io. Besides that, the code is pretty simple, containing basically some function definition and passing, and some recursion here and there.

In line 6 we start the script execution by calling the function processDir on the current directory. An interesting part of this function is the pattern matching at the lines 13-16 where we get the current file extension, which we will use in the if statement that follows. There, we simply ignore files that have no extension (i.e. got defined as None), or are not .sql or .java.

For the correct files, processFile is then called. From here, all that happens is basic Java IO stuff, except for one interesting code on line 29.  Here, for each string that is matched by the regex, we replace it by a new version, generate by the replaceUnicode function. This is probably the most interesting line in the entire script.


Scala Problem Number Two

Following with my take on the Scala 99 Problems that I started here, lets talk a little bit about the second one. Here is the problem definition, from the original page:

P02 (*) Find the last but one element of a list.
Example:

scala> penultimate(List(1, 1, 2, 3, 5, 8))
res0: Int = 5

This one is very similar to the last problem and has similar solutions as well. The first solution I tried was, again, an ugly one:

def penultimate[A](list: List[A]): A = {
  list(list.size-2)
}

Terrible, but works. The second solution is nicer, with pattern matching, as before. But this time I learned a little bit from Phil Gold’s solution for the first problem, so prettier it is:

def penultimateWithPatternMatching[A](list: List[A]): A = list match {
  case x :: y :: Nil => x
  case _ :: tail => penultimateWithPatternMatching(tail)
  case _ => throw new NoSuchElementException
}

You can find Phil Gold’s solution to this problem here. His simpler solution is a bit better than mine, so my mind expands a little bit and I learn =). Also, he plays with a generic finder – interesting to read, and more mind expanding happens.


Ninety-Nine Scala Problems

Listening to a few different podcasts (The Java Posse among them), I found out about Ninety-Nine Scala Problems. As the description on the site says, it is an adaptation of the original Ninety-Nine Prolog Problems. I find the idea very interesting and decided to give it a go.

In summary, this is a bunch of (sort-of) small problems to be solved. You can use them to improve your knowledge in a programming language – Scala in this case. I won’t pretend I know where this trend started, but whoever had this idea for the first time, kudos to you!

During the next (bunch of, a lot of, certainly not few) weeks I’ll go through the problems trying to solve them, and post my impressions here. Those impressions will most likely contain my solutions, so please bear that in mind if you intend to try to solve the problems yourself as well. Also, the page mentioned above with the problems has possible solutions available and I’ll mention them, with links to the originals.

US_99

US_99

To allow you to understand what that feels like, lets talk about the first problem, which is really easy.

The definition of the first problem says:

P01 (*) Find the last element of a list.
     Example:
     scala> last(List(1, 1, 2, 3, 5, 8))
     res0: Int = 8

I came up with basically two solutions. One that is pretty obvious and ugly, using the size of the list:

def last(list: List[Any]): Any = {
  list(list.size-1)
}

The other solution used Pattern Matching to decompose the list, until we have only the last element:

def lastUsingCase(list: List[Any]): Any = list match {
  case x :: Nil => x
  case x :: list => lastUsingCase(list)
  case _ => Unit
}

Phil Gold”s solutions include one Pattern Matching version, which is a little more elegant than mine, and a version using a built in feature that gives direct access to the last element of the list (the last function). I didn’t know about this function, so I already learned something new from this whole 99 Problems thing =) You can find Phil Gold’s solutions for this problem here.


Scala Pattern Matching: the reason to fall in love with Scala

Scala has a lot of interesting features and, among them, one of the most interesting ones is Pattern Matching. If you still need a reason to try Scala this is the one. Actually, I might be exaggerating a little bit, but this feature is really interesting. Really. ;)

In summary, Pattern Matching looks like switch statements in Java. But there are a couple of things to keep in mind:

  • Using switch statements in Java is usually a code smell, i.e., something to avoid, risking your good OO design. This is not the case in Scala, where pattern matching is a core feature of the language, and should be leveraged by your applications.
  • Unlike in Java, there is basically no limits in terms of what you can use in the case clause. This, combined with the fact that Scala is a functional language, letting you pass functions around, gives you insane flexibility.

Lets go through a (very) simple example so that you can see by yourself at least part of this power. Suppose you are writing a function that takes an object of any type, and prints some information about it. Here is how you could do this:

class PrettyPrinter {
  def print(obj: Any) = {
    obj match {
      case 1 => println("number one")
      case Client("john") => println("special client: john")
      case Client(name) => println("client: " + name)
      case other => println(other)
    }
  }
}
case class Client(name: String)

object PatternMatchingTest {
  def main(args: Array[String]): Unit = {
    var printer = new PrettyPrinter
    printer.print(1)
    printer.print(new Client("jcranky"))
    printer.print(new Client("john"))
    printer.print("RandomStuff")
  }
}

Notice that, in the same clause, we are matching:

  • an integer number;
  • a specific Client
  • any other Client
  • any object of any class

Very flexible. For instance, in the case where we match any client, notice also that we capture the client’s name “automagically”, and use it in the println call.

That’s all for now. What do you think? Is this powerful enough for you? =D

EDIT:

I forgot to mention the expected output of the code above… so here it is:


number one
client: jcranky
special client: john
RandomStuff


Follow

Get every new post delivered to your Inbox.