Example of Implicit Conversions, Options, Extractors and Tuples

While writing a new web service resource today I had the chance to use some pretty awesome parts of Scala, and wanted to share some of them.  We integrate with Twitter and have a POJO like this TwitterUser class:

package com.pongr.twitter;

public class TwitterUser
{
    private String name;

    public TwitterUser()
    {
        this(null);
    }

    public TwitterUser(String name)
    {
        setName(name);
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }
}

It’s been stripped down to only the relevant property, in this case the user’s full name that they specified on their Twitter account.  This new resource sends back various information about a user to our mobile apps, including their Twitter info.  Since I wrote this new resource in Scala I decided to “scalafy” (scalify?) the TwitterUser class a bit.

First off, one of our users may not have linked to their Twitter account, so the TwitterUser object might be null.  And even if they have, the name we get back from the Twitter API will be null if they haven’t entered a name, or may just be a duplicate of their screen name (like @zcox).  We need to split up the name into valid first and last names, so this seemed like a good place to be using an Option[String] instead of just a String, which is a best practice from the Beginning Scala book.  So the TwitterInfo class ended up looking like this:

package com.pongr.twitter

class TwitterInfo(user: Option[TwitterUser]) {
  val NameRegex = """(.*?)\s+(.*)""".r
  val name = user.flatMap(_.getName match {
    case NameRegex(first, last) => Some((first, last))
    case _ => None
  })
  val firstName = name.map(_._1)
  val lastName = name.map(_._2)
}

object TwitterInfo {
  implicit def twitterUser2TwitterInfo(user: TwitterUser) = new TwitterInfo(if (user == null) None else Some(user))
}

Another thing to note is the use of a regular expression as an extractor to split up the Twitter name into separate first and last names.  I picked up this technique from the Programming in Scala book and I have to say that it makes the code incredibly intuitive.  I also made the name field a tuple to reuse this regular expression extraction: the firstName and lastName fields are then initialized to the first and second parts of it, respectively.

Implicit conversions continue to amaze me so I created the twitterUser2TwitterInfo method that converts a TwitterUser object into a TwitterInfo.  Putting all of this together, we can use this TwitterInfo class to safely obtain the user’s Twitter name:

package com.pongr.twitter

import TwitterInfo._

object App {
  def main(args : Array[String]) : Unit = {
    print(new TwitterUser)
    print(new TwitterUser("asdf"))
    print(new TwitterUser("John Smith"))
  }

  def print(user: TwitterUser) = println(user.lastName.getOrElse("N/A") + ", " + user.firstName.getOrElse("N/A"))
}

The implicit conversion lets us (appear to) call TwitterInfo methods right on the TwitterUser object, and since the firstName and lastName fields are each an Option[String] we can gracefully handle the case where we don’t have the Twitter name.  Running the above test app prints out the following:

N/A, N/A
N/A, N/A
Smith, John

I know this is a pretty simple example, but I thought it was a practical demonstration of some of the techniques that make Scala such a fun language to program with.

Advertisements

One thought on “Example of Implicit Conversions, Options, Extractors and Tuples

  1. Pingback: Twitter Trackbacks for Example of Implicit Conversions, Options, Extractors and Tuples « Zach's Blog [zcox.wordpress.com] on Topsy.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s