Scala Saturday – Pattern Matching, Part 1

A terribly useful technique in functional programming is pattern matching. Pattern matching is simply a form of conditional logic, like an if-else expression or (in other languages) a switch statement, but quite a bit more powerful and flexible. With pattern matching, you can perform matches and take action based on simple values, such as integers, but also on complex types and the values of their members. Here are some examples using the simpler types, and a future post(s) will illustrate how to match on more complex types.

On the Whole (Numbers)

Pattern matching on integers is very straightforward. Just use literals:

def getResponse(talents: Int) = talents match {
  case 5 => "Here are your five talents plus five more"
  case 2 => "Here are your two talents plus two more"
  case 1 => "Here is your one talent, which I hid"
  case _ => "Uh, wrong story"
}

val response = getResponse(5)
// response: String = 
//   Here are your five talents plus five more

val apocryphal = getResponse(42)
// apocryphal: String = Uh, wrong story

Of course, the set of all possible integers is very large. Our example here only covers three specific values: 1, 2, and 5. To cover every other case that you don’t specify explicitly, use the wildcard pattern _, the underscore. That’s how we could handle 42. Or 103. Or −7. Or any other integer.

Getting to the (Floating) Point

Floating point numbers are difficult to pin down because of the margin of error, so you don’t typically match on a specific number. Usually you match on ranges. Pattern matching allows for that, too:

def getState(temp: Double) = temp match {
  case x if x <= 32.0 => "solid"
  case x if x >= 212.0 => "gas"
  case _ => "liquid"
}

val atRoomTemp = getState(70.0)
// atRoomTemp: String = liquid

val atSouthPole = getState(-70.6)
// atSouthPole: String = solid

Putting a condition on a match with the if keyword like that is called a guard. Guards are simply Boolean expressions. You could alternatively write the “liquid” step in getState with a compound Boolean expression:

def getState2(temp: Double) = temp match {
  case x if 32.0 > x && x < 212.0 => "liquid"
  case x if x >= 212.0 => "gas"
  case _ => "solid"
}
  
val onHotSummerDay = getState2(98.5)
// onHotSummerDay: String = solid

In one more rewrite of getState, note that it is possible to use variables, not just literals, in guards:

def getState3(temp: Double) = {
  val freezingPoint = 32.0
  val boilingPoint = 212.0
  temp match {
    case x if x <= freezingPoint => "solid"
    case x if x >= boilingPoint => "gas"
    case _ => "liquid"
  }
}

val inDeathValley = getState3(134.0)
// inDeathValley: String = liquid

Stringly Typed Interfaces

Perhaps your application executes commands, and those commands are specified by names, that is, strings. (Some folks jokingly call them “stringly typed interfaces.”) Pattern matching is perfect for this task:

def execute(command: String, id: Int, value: String = "") =
  command match {
    case "add" => s"Added ${id}: ${value}"
    case "remove" => s"Added ${id}"
    case "update" => s"Added ${id}: ${value}"
    case _ => s"Illegal command: ${command}"
  }

val added = execute("add", 42, "foo")
// added: String = Added 42: foo

val updated = execute("update", 42, "bar")
// updated: String = Added 42: bar

val removed = execute("remove", 42)
// removed: String = Added 42

val wowbanged = execute("wowbang", 73)
// wowbanged: String = Illegal command: wowbang

Perhaps you want to allow some flexibility in your command names. For example, another name for “add” could be “create.” Pattern matching expressions allow you to stack multiple conditions for which you want to take the same action using a pipe (|):

def execute2(command: String, id: Int, value: String = "") =
  command match {
    case "add" | "create" => s"Added ${id}: ${value}"
    case "remove" | "delete" => s"Added ${id}"
    case "update" | "change" => s"Added ${id}: ${value}"
    case _ => s"Illegal command: ${command}"
  }

val created = execute2("create", 84, "baz")
// created: String = Added 84: baz

Here Are Your Options

Perhaps you have a user variable that is an Option[String]. If the user is logged in, user is a Some; otherwise the user is an unauthenticated guest. You’d like to generate a greeting based on whether the user is logged in or not:

def greet(user: Option[String]) = user match {
  case Some(name) => s"Welcome back, ${name}!"
  case None => "Hello, dear guest! Please sign in!"
}

val personal = greet(Some("bcollins"))
// personal: String = Welcome back, bcollins!

val generic = greet(None)
// generic: String = 
//   Hello, dear guest! Please sign in!

Notice how the match expression can, in the case of the Some, unpack the value for you and assign it to a variable, name in this case. You don’t have to do it yourself.

Now given that Option is a binary choice, you may be tempted to think that an if-else block is probably a better, um, option. In some simple cases it may be, but in this case, you want to generate a message that differs by more than just the username. Look at what it takes to get the same results with an if-else block as the match expression above:

def greet2(user: Option[String]) =
  if (user.isDefined) {
    val name = user.get
    s"Welcome back, ${name}!"
  } else {
    "Hello, dear guest! Please sign in!"
  }

Now that’s not too bad, but compare that to the original version that uses the match expression. The match expression is just cleaner: It is very easy to see what the conditions are, and you don’t have to clutter the code by unpacking the Some value yourself.

Bearing with the Tuples of the Week

Pattern matching expressions can unpack tuples so that you can match on all values or individual values:

def getProducer(chars: (String, String)) =
  chars match {
    case ("Tom", "Jerry") => "Hanna-Barbera"
    case ("Bugs", "Daffy") => "Warner Brothers"
    case ("Mickey", _) => "Disney"
    case (x, "Buzz") => s"Pixar with ${x} and Buzz"
    case _ => "other"
  }

val prod = getProducer("Tom", "Jerry")
// prod: String = Hanna-Barbera

val prod2 = getProducer("Mickey", "Minnie")
// prod2: String = Disney

val prod3 = getProducer("Mickey", "Donald")
// prod3: String = Disney

val prod4 = getProducer("Woody", "Buzz")
// prod4: String = Pixar with Woody and Buzz

val prod5 = getProducer("Andy", "Buzz")
// prod5: String = Pixar with Andy and Buzz

val prod6 = getProducer("Ren", "Stimpy")
// prod6: String = other

As you can see in the “Disney” line, you don’t care what the second element of the tuple is, so you throw it away with the wildcard pattern. On the other hand, on the “Pixar …” line, you want to capture the first element in the matched tuple and use it in the result. So you just give it a variable name, and the compiler assigns the value to the variable for you, just like with Some(name) above.

What’s Your Type?

Finally, pattern matching expressions can match even on different types and take action based on the type of the input:

def report(guests: Any) = guests match {
  case guest: String =>
    s"Our guest: ${guest}"
  case all: Array[String] =>
    s"Our guests: ${all.mkString(", ")}"
  case count: Int =>
    s"We have ${count} guests"
  case _ => "Huh?"
}

val one = report("Brad")
// one: String = Our guest: Brad

val many = report(Array("Me", "Myself", "I"))
// many: String = Our guests: Me, Myself, I

val count = report(13)
// count: String = We have 13 guests

val stumped = report(3.14)
// stumped: String = Huh?

As you can see, you can choose from any number of types to match on and take action accordingly.

F# Friday – Pattern Matching, Part 1

A terribly useful technique in functional programming is pattern matching. Pattern matching is simply a form of conditional logic, like an if-else expression or (in other languages) a switch statement, but quite a bit more powerful and flexible. With pattern matching, you can perform matches and take action based on simple values, such as integers, but also on complex types and the values of their members. Here are some examples using the simpler types, and a future post(s) will illustrate how to match on more complex types.

On the Whole (Numbers)

Pattern matching on integers is very straightforward. Just use literals:

let getResponse talents =
    match talents with
    | 5 -> "Here are your five talents plus five more"
    | 2 -> "Here are your two talents plus two more"
    | 1 -> "Here is your one talent, which I hid"
    | _ -> "Uh, wrong story"

let response = getResponse 5
// val response : string = 
//   "Here are your five talents plus five more"

let apocryphal = getResponse 42
// val apocryphal : string = "Uh, wrong story"

Of course, the set of all possible integers is very large. Our example here only covers three specific values: 1, 2, and 5. To cover every other case that you don’t specify explicitly, use the wildcard pattern _, the underscore. That’s how we could handle 42. Or 103. Or −7. Or any other integer.

Getting to the (Floating) Point

Floating point numbers are difficult to pin down because of the margin of error, so you don’t typically match on a specific number. Usually you match on ranges. Pattern matching allows for that, too:

let getState temp =
    match temp with
    | x when x <= 32.0 -> "solid"
    | x when x >= 212.0 -> "gas"
    | _ -> "liquid"

let atRoomTemp = getState 70.0
// val atRoomTemp : string = "liquid"

let atSouthPole = getState -70.6
// val atSouthPole : string = "solid"

Putting a condition on a match with the when keyword like that is called a guard. Guards are simply Boolean expressions. You could alternatively write the “liquid” step in getState with a compound Boolean expression:

let getState2 temp =
    match temp with
    | x when 32.0 > x && x < 212.0 -> "liquid"
    | x when x >= 212.0 -> "gas"
    | _ -> "solid"
let onHotSummerDay = getState2 98.5
// val onHotSummerDay : string = "liquid"

In one more rewrite of getState, note that it is possible to use variables, not just literals, in guards:

let getState3 temp =
    let freezingPoint = 32.0
    let boilingPoint = 212.0
    match temp with
    | x when x <= freezingPoint -> "solid"
    | x when x >= boilingPoint -> "gas"
    | _ -> "liquid"
let inDeathValley = getState3 134.0
// val inDeathValley : string = "liquid"

Stringly Typed Interfaces

Perhaps your application executes commands, and those commands are specified by names, that is, strings. (Some folks jokingly call them “stringly typed interfaces.”) Pattern matching is perfect for this task:

let execute command id value =
    let v = defaultArg value ""
    match command with
    | "add" -> sprintf "Added %d: %s" id v
    | "remove" -> sprintf "Added %d" id
    | "update" -> sprintf "Added %d: %s" id v
    | _ -> sprintf "Illegal command: %s" command

let added = execute "add" 42 (Some "foo")
// val added : string = "Added 42: foo"

let removed = execute "remove" 42 None
// val removed : string = "Added 42"

let updated = execute "update" 42 (Some "bar")
// val updated : string = "Added 42: bar"

let wowbanged = execute "wowbang" 73 None
// val wowbanged : string = "Illegal command: wowbang"

Perhaps you want to allow some flexibility in your command names. For example, another name for “add” could be “create.” Pattern matching expressions allow you to stack multiple conditions for which you want to take the same action:

let execute2 command id value =
    let v = defaultArg value ""
    match command with
    | "create"
    | "add" -> sprintf "Added %d: %s" id v
    | "delete"
    | "remove" -> sprintf "Added %d" id
    | "change"
    | "update" -> sprintf "Added %d: %s" id v
    | _ -> sprintf "Illegal command: %s" command
let created = execute2 "create" 84 (Some "baz")
// val created : string = "Added 84: baz"

Here Are Your Options

Perhaps you have a user variable that is a string option. If the user is logged in, user is a Some; otherwise the user is an unauthenticated guest. You’d like to generate a greeting based on whether the user is logged in or not:

let greet user =
    match user with
    | Some name -> sprintf "Welcome back, %s!" name
    | None -> "Hello, dear guest! Please sign in!"

let personal = greet (Some "bcollins")
// val personal : string = "Welcome back, bcollins!"

let generic = greet None
// val generic : string = 
//   "Hello, dear guest! Please sign in!"

Notice how the match expression can, in the case of the Some, unpack the value for you and assign it to a variable, name in this case. You don’t have to do it yourself.

Now given that Option is a binary choice, you may be tempted to think that an if-else block is probably a better, um, option. In some simple cases it may be, but in this case, you want to generate a message that differs by more than just the username. Look at what it takes to get the same results with an if-else block as the match expression above:

let greet2 user =
    if Option.isSome user then
        let name = Option.get user
        sprintf "Welcome back, %s!" name
    else
        "Hello, dear guest! Please sign in!"

Now that’s not too bad, but compare that to the original version that uses the match expression. The match expression is just cleaner: It is very easy to see what the conditions are, and you don’t have to clutter the code by unpacking the Some value yourself.

Bearing with the Tuples of the Week

Pattern matching expressions can unpack tuples so that you can match on all values or individual values:

let getProducer chars =
    match chars with
    | ("Tom", "Jerry") -> "Hanna-Barbera"
    | ("Bugs", "Daffy") -> "Warner Brothers"
    | ("Mickey", _) -> "Disney"
    | (x, "Buzz") -> sprintf "Pixar with %s and Buzz" x
    | _ -> "other"

let prod = getProducer ("Tom", "Jerry")
// val prod : string = "Hanna-Barbera"

let prod2 = getProducer ("Mickey", "Minnie")
// val prod2 : string = "Disney"

let prod3 = getProducer ("Mickey", "Donald")
// val prod3 : string = "Disney"

let prod4 = getProducer ("Woody", "Buzz")
// val prod4 : string = "Pixar with Woody and Buzz"

let prod5 = getProducer ("Andy", "Buzz")
// val prod5 : string = "Pixar with Andy and Buzz"

let prod6 = getProducer ("Ren", "Stimpy")
// val prod6 : string = "other"

As you can see in the “Disney” line, you don’t care what the second element of the tuple is, so you throw it away with the wildcard pattern. On the other hand, on the “Pixar …” line, you want to capture the first element in the matched tuple and use it in the result. So you just give it a variable name, and the compiler assigns the value to the variable for you, just like with Some name above.

What’s Your Type?

Finally, pattern matching expressions can match even on different types and take action based on the type of the input:

let report (guests : obj) =
    match guests with
    | :? string as guest -> 
        sprintf "Our guest: %s" guest
    | :? (string array) as all -> 
        (all |> String.concat ", ")
        |> sprintf "Our guests: %s"
    | :? int as count -> 
        sprintf "We have %d guests" count
    | _ -> "Huh?"

let one = report "Brad"
// val one : string = "Our guest: Brad"

let many = report [|"Me"; "Myself"; "I"|]
// val many : string = "Our guests: Me, Myself, I"

let count = report 13
// val count : string = "We have 13 guests"

let stumped = report 3.14
// val stumped : string = "Huh?"

As you can see, you can choose from any number of types to match on and take action accordingly. Note that if the input argument does not contain a type annotation, such as (guests : obj) above, the compiler refuses to compile.

Scala Saturday – The Set.diff Method

Sometimes you have two sets of information, and you want to know what is in one set that the other set lacks. You want to perform a set difference operation.

What’s the Difference?

Given two sets, A and B, the difference between A and B—the items in A that are not in B—is written as follows:

A \ B

Likewise, the difference in B and A—the items in B that are not in A—is written vice versa:

B \ A

Set operations are frequently easiest to convey with a diagram:

An illustration of two sets, A and B, represented as two filled circles that are slightly overlapping. The difference (A \ B) is the part of set A not overlapping set B. The difference (B \ A) is the part of set B not overlapping set A.
The Difference in Two Sets A and B

It’s worth noting that a set difference operation is like arithmetic subtraction in that it matters which operand comes first. That is …

A \ B ≠ B \ A

White & nerdy mathematicians say that the set difference operation does not commute.

Always Never the Same

Continuing with my penchant for using band lineups as examples, put the original lineup of the band Kansas in one set and the current lineup in another:

val original = Set(
  "Walsh", "Livgren", "Williams",
  "Steinhardt", "Hope", "Ehart")
val current = Set(
  "Platt", "Manion", "Williams",
  "Ragsdale", "Greer", "Ehart")

To get the original members no longer with the band, use the Set.diff method to take the difference in the original lineup and the current:

val departed = original.diff(current)
// departed: scala.collection.immutable.Set[String] = 
//   Set(Walsh, Steinhardt, Livgren, Hope)

To get the current members who were not in the original lineup, do the opposite—take the difference in the current lineup and the original:

val noobs = current.diff(original)
// noobs: scala.collection.immutable.Set[String] = 
//   Set(Platt, Ragsdale, Manion, Greer)

How ’bout that! Simple enough, I suppose, but seeing as set difference is a whole lot like arithmetic subtraction, wouldn’t it be really nice if we could express our set difference operations just like we do arithmetic subtraction?

A − B

Good news: You can! Well, almost. Scala defines a -- operator so that we can more mathematical-looking code:

val departed = original -- current
val noobs = current -- original
// departed: scala.collection.immutable.Set[String] = 
//   Set(Walsh, Steinhardt, Livgren, Hope)
// noobs: scala.collection.immutable.Set[String] = 
//   Set(Platt, Ragsdale, Manion, Greer)

Incidentally, Scala does also define a minus operator, but it is for removing one item at a time, not a set of items. However, with it you can write code like this:

val noRhythm = current - "Ehart" - "Greer"
// noRhythm: scala.collection.immutable.Set[String] = 
//   Set(Platt, Ragsdale, Manion, Williams)

F# Friday – The Set.difference Function

Sometimes you have two sets of information, and you want to know what is in one set that the other set lacks. You want to perform a set difference operation.

What’s the Difference?

Given two sets, A and B, the difference between A and B—the items in A that are not in B—is written as follows:

A \ B

Likewise, the difference in B and A—the items in B that are not in A—is written vice versa:

B \ A

Set operations are frequently easiest to convey with a diagram:

An illustration of two sets, A and B, represented as two filled circles that are slightly overlapping. The difference (A \ B) is the part of set A not overlapping set B. The difference (B \ A) is the part of set B not overlapping set A.
The Difference in Two Sets A and B

It’s worth noting that a set difference operation is like arithmetic subtraction in that it matters which operand comes first. That is …

A \ B ≠ B \ A

White & nerdy mathematicians say that the set difference operation does not commute.

Always Never the Same

Continuing with my penchant for using band lineups as examples, put the original lineup of the band Kansas in one set and the current lineup in another:

let original =
    set ["Walsh"; "Livgren"; "Williams";
         "Steinhardt"; "Hope"; "Ehart"]
let current = 
    set ["Platt"; "Manion"; "Williams";
         "Ragsdale"; "Greer"; "Ehart"]

To get the original members no longer with the band, use the Set.difference function to take the difference in the original lineup and the current:

let departed = Set.difference original current
// val departed : Set<string> =
//   set ["Hope"; "Livgren"; "Steinhardt"; "Walsh"]

To get the current members who were not in the original lineup, do the opposite—take the difference in the current lineup and the original:

let noobs = Set.difference current original
// val noobs : Set<string> = 
//   set ["Greer"; "Manion"; "Platt"; "Ragsdale"]

How ’bout that! Simple enough, I suppose, but seeing as set difference is a whole lot like arithmetic subtraction, wouldn’t it be really nice if we could express our set difference operations just like we do arithmetic subtraction?

A − B

Good news: You can! F# defines a minus operator so that we can do exactly that:

let departed = original - current
let noobs = current - original
// val departed : Set<string> = 
//   set ["Hope"; "Livgren"; "Steinhardt"; "Walsh"]
// val noobs : Set<string> = 
//   set ["Greer"; "Manion"; "Platt"; "Ragsdale"]

Scala Saturday – The Option Type, Part 3

One more word on the Option type. While Option allows you a more type-safe alternative to nulls, it does not itself handle nulls. In other words, this …

val s = Some(null)

… gets you a Some containing a null. That doesn’t help so much if our aim is to get away from null, not kick it down the road.

The Java Way

In version 8, Java introduced its own Optional type, no doubt inspired by the Option and Maybe types available in the functional languages. It does handle nulls. Take the following classes as examples:

public class User {
  private String username;
  private String name;
  
  public User(String username) { this(username, null); }
  public User(String username, String name) {
    this.username = username;
    this.name = name;
  }
  
  public String getUsername() { return username; }
  public String getName() { return name; }
}

public class Session {
  private User user;
  
  public Session() { this(null); }
  public Session(User u) { this.user = u; }
  
  public User getUser() { return user; }
}

public class Application {
  private Session session;

  public Application() { this(null); }
  public Application(Session s) { this.session = s; }
  
  public Session getSession() { return session; }
}

Because Optional handles null in its map operation, this works:

Application app = new Application(new Session());
String name = Optional.of(app)
                .map(Application::getSession)
                .map(Session::getUser)
                .map(User::getName)
                .orElse("n/a");
// name = "n/a"

In our example, the Session has a null User property. But that’s OK, because the map operation on line 4 (highlighted above) takes that null and converts it to a None, or more accurately, an Empty per Java parlance.

Back in Scala Land

We cannot do quite the same thing in Scala. Now we, as enlightened Scala developers, would never code up something that uses nulls all over the place like the Java classes above. But the Java world is more comfortable with nulls, so let’s say that you are working with a library that contains those Java classes. You pull the JAR into your Scala project and write something like this:

val app = new Application(new Session())
val name = Option(app)
             .map(_.getSession)
             .map(_.getUser)
             .map(_.getName)
             .getOrElse("n/a")
// NullPointerException!!!

But that breaks down pretty quickly. Line 4 (highlighted above) yields an exception because _.getUser is null. Option.map in Scala does not convert a null to a None. So then, what do we do?

Well, you can instantiate an Option by applying the Option object. Option() does take an object reference and return a None if it is a null, or a Some if it is not. Also, remember that Option.flatMap takes an operation that returns an Option and flattens it so that it does not return a nested Option, but just an Option. Therefore, you can change your code to this:

let app = Application(Session())
val name = Option(app)
             .flatMap(a => Option(a.getSession))
             .flatMap(s => Option(s.getUser))
             .flatMap(u => Option(u.getName))
             .getOrElse("n/a")
// name : String = "n/a"

It’s a bit more headache than you’d like, but that’s what you get for using flaky Java code, right?

F# Friday – The Option Type, Part 3

One more word on the Option type. While Option allows you a more type-safe alternative to nulls, it does not itself handle nulls. In other words, this …

let s = Some null

… gets you a Some containing a null. That doesn’t help so much if our aim is to get away from null, not kick it down the road.

The Java Way

In version 8, Java introduced its own Optional type, no doubt inspired by the Option and Maybe types available in the functional languages. It does handle nulls. Take the following classes as examples:

public class User {
  private String username;
  private String name;
  
  public User(String username) { this(username, null); }
  public User(String username, String name) {
    this.username = username;
    this.name = name;
  }
  
  public String getUsername() { return username; }
  public String getName() { return name; }
}

public class Session {
  private User user;
  
  public Session() { this(null); }
  public Session(User u) { this.user = u; }
  
  public User getUser() { return user; }
}

public class Application {
  private Session session;

  public Application() { this(null); }
  public Application(Session s) { this.session = s; }
  
  public Session getSession() { return session; }
}

Because Optional handles null in its map operation, this works:

Application app = new Application(new Session());
String name = Optional.of(app)
                .map(Application::getSession)
                .map(Session::getUser)
                .map(User::getName)
                .orElse("n/a");
// name = "n/a"

In our example, the Session has a null User property. But that’s OK, because the map operation on line 4 (highlighted above) takes that null and converts it to a None, or more accurately, an Empty per Java parlance.

Back in .NET Land

We cannot do quite the same thing in F#. Now we, as enlightened F# developers, would never code up something that uses nulls all over the place like the Java classes above. But the C# world is more comfortable with nulls, so let’s say that you are working with a C# library that contains the analogs to the Java classes above:

public class User
{
    public string Username { get; private set; }
    public string Name { get; private set; }

    public User(string username, string name = null)
    {
        Username = username;
        Name = name;
    }
}

public class Session
{
    public User User { get; private set; }

    public Session(User u = null) { User = u; }
}

public class Application
{
    public Session Session { get; private set; }

    public Application(Session s = null) { Session = s; }
}

You pull that library into your F# project and write something like this:

let app = Application(Session())
let name =
    Some app
    |> Option.map (fun a -> a.Session)
    |> Option.map (fun s -> s.User)
    |> Option.map (fun u -> u.Name)
    |> defaultArg <| "n/a"
// NullReferenceException!!!

But that breaks down pretty quickly. Line 5 (highlighted above) yields an exception because s.User is null. Option.map in F# does not convert a null to a None. So then, what do we do?

Well, if you’re using F# 4.0, there is something new to the Option module: Option.ofObj. It is essentially a named constructor for Option. It takes an object reference and returns a None if it is a null, or a Some if it is not. Also, remember that Option.bind takes an operation that returns an Option and flattens it so that it does not return a nested Option, but just an Option. Therefore, you can change your code to this:

let app = Application(Session())
let name = 
    Some app
    |> Option.bind (fun a -> Option.ofObj a.Session)
    |> Option.bind (fun s -> Option.ofObj s.User)
    |> Option.bind (fun u -> Option.ofObj u.Name)
    |> defaultArg <| "n/a"
// name : string = "n/a"

It’s a bit more headache than you’d like, but that’s what you get for using flaky C# code, right?

If you’re not using F# 4.0 yet, then you can write a little utility function to do the same job:

let nullToOption = function 
                   | null -> None
                   | x -> Some x

let app = Application(Session())
let name = 
    Some app
    |> Option.bind (fun a -> nullToOption a.Session)
    |> Option.bind (fun s -> nullToOption s.User)
    |> Option.bind (fun u -> nullToOption u.Name)
    |> defaultArg <| "n/a"
// name : string = "n/a"

Scala Saturday – The Option Type, Part 2

Last week we introduced the Option type as a way of representing when a function may or may not return a value.

A Collection of One

Another way to think about an Option is as a collection that contains no more than one element. Consequently, Option provides some collection-like semantics, e.g., fold, map, exists, and filter. This allows us to chain operations together without having to check at each step whether the value is Some or None. We can put that off until the end of the sequence of operations and only do the check once. That way, the algorithm is more readable; it’s not cluttered with a bunch of if-else noise.

Say that you have a User type:

case class User(id: String, name: String)

Let’s say that your system is a website. In the top, right corner of the site, you want to display the name of the user who is currently logged in. You need a function that returns the user currently signed in:

val authenticatedUser: () => Option[User] = // ...

Now why would this function return an Option? Well, the user browsing your site may not have logged in at this point. If that’s the case, then the current user is None. So then, the code to get the name of the current user is this:

val nameOpt = authenticatedUser().map(_.name)
// nameOpt: Option[String]

Notice how the type of nameOpt is Option[String]. In other words, assuming that authenticatedUser() returns a Some[User], Scala knows that the User.name property is a String. Nevertheless it propagates the uncertainty, if you will, along through the map operation. Any operations you do on an Option only happen if the Option is a Some. Otherwise, Scala happily ignores the operation and continues to propagate the None.

OK, so now that we have a final result Option, what do we do with it? That’s where Option.getOrElse() comes in:

val name = nameOpt getOrElse "Guest"
// name: String

If nameOpt is a Some, name is the value in the Some. If nameOpt is a None, then name is "Guest". You can test both cases in the Scala REPL. To see it work in the case of a Some:

val authenticatedUser: () => Option[User]  =
    () => Some(User("bcollins", "Brad Collins"))
val name = authenticatedUser()
             .map(_.name)         // Some("Brad Collins")
             .getOrElse("Guest")  // "Brad Collins"
// name: String = Brad Collins

And then to see it with a None:

val authenticatedUser: () => Option[User]  =
    () => None
val name = authenticatedUser()
             .map(_.name)         // None
             .getOrElse("Guest")  // "Guest"
// name: String = Guest

Unraveling the Options

Remember how the collections API defines the flatMap method? For instance, this is the List.flatMap() method:

// signature slightly modified for readability
def flatMap[B](f: (A) ⇒ List[B]): List[B]

It’s like map, but flatMap takes a transformation function that takes an element and returns a list of values rather than just a single value. Then instead of returning a list of lists, flatMap flattens them into a single list.

Option also has a flatMap method. It takes a function that returns an Option and, instead of returning a nested Option (i.e., an Option[Option[B]]), it just returns an Option[B]:

def flatMap[B](f: (A) ⇒ Option[B]): Option[B]

Maybe instead of having an authenticatedUser() function, your app just has a session property. To get the name of the current user, you have to walk the property tree from the application to the session to the user and then finally the name. Application.session is an Option to indicate that there may be no valid session. Session.user is an Option to indicate that there may be no user signed in. Finally, maybe we don’t even force a user to have a name, just a user ID:

case class User(id: String, name: Option[String] = None)
case class Session(user: Option[User] = None)
case class Application(session: Option[Session] = None)

You walk the property tree like this:

val nameOpt = app.session
                .flatMap(_.user)
                .flatMap(_.name)
val name = nameOpt getOrElse "Guest"

Now if any property is None, from session to user to name, nameOpt is None, and name is "Guest".

F# Friday – The Option Type, Part 2

Last week we introduced the Option type as a way of representing when a function may or may not return a value.

A Collection of One

Another way to think about an Option is as a collection that contains no more than one element. Consequently, the Option module provides some collection-like semantics, e.g., fold, map, exists, and even filter in F# 4.0. This allows us to chain operations together without having to check at each step whether the value is Some or None. We can put that off until the end of the sequence of operations and only do the check once. That way, the algorithm is more readable; it’s not cluttered with a bunch of if-else noise.

Say that you have a User type:

type User(id : string, name : string) =
    member x.Id = id
    member x.Name = name

Let’s say that your system is a website. In the top, right corner of the site, you want to display the name of the user who is currently logged in. You need a function that returns the user currently signed in:

let authenticatedUser : unit -> User option = // ...

Now why would this function return an Option? Well, the user browsing your site may not have logged in at this point. If that’s the case, then the current user is None. So then, the code to get the name of the current user is this:

let nameOpt = authenticatedUser()
              |> Option.map (fun u -> u.Name)
// val nameOpt : string option

Notice how the type of nameOpt is string option. In other words, assuming that authenticatedUser() returns a Some<User>, F# knows that the User.Name property is a string. Nevertheless it propagates the uncertainty, if you will, along through the map operation. Any operations you do on an Option only happen if the Option is a Some. Otherwise, F# happily ignores the operation and continues to propagate the None.

OK, so now that we have a final result Option, what do we do with it? That’s where defaultArg comes in:

let name = defaultArg nameOpt "Guest"
// val name : string

If nameOpt is a Some, name is the value in the Some. If nameOpt is a None, then name is "Guest". You can test both cases in the F# REPL. To see it work in the case of a Some:

let authenticatedUser : unit -> User option =
    fun () -> Some(User("bcollins", "Brad Collins"))
let nameOpt = authenticatedUser()
              |> Option.map (fun u -> u.Name)
// val nameOpt : string option = Some "Brad Collins"
let name = defaultArg nameOpt "Guest"
// val name : string = "Brad Collins"

And then to see it with a None:

let authenticatedUser : unit -> User option =
    fun () -> None
let nameOpt = authenticatedUser()
              |> Option.map (fun u -> u.Name)
// val nameOpt : string option = None
let name = defaultArg nameOpt "Guest"
// val name : string = "Guest"

Unraveling the Options

Remember how the collections modules define the collect function? For instance, this is the List.collect() function:

List.collect : ('T -> 'U list) -> 'T list -> 'U list

It’s like map, but collect takes a transformation function that takes an element and returns a list of values rather than just a single value. Then instead of returning a list of lists, collect flattens them into a single list.

Option has a similar function: bind. The bind operation takes a function that returns an Option and, instead of returning a nested Option (i.e., an Option<Option<'U>>, it just returns an Option<'U>:

Option.bind : ('T -> 'U option) -> 'T option -> 'U option

Maybe instead of having an authenticatedUser() function, your app just has a Session property. To get the name of the current user, you have to walk the property tree from the application to the session to the user and then finally the name. App.Session is an Option to indicate that there may be no valid session. Session.User is an Option to indicate that there may be no user signed in. Finally, maybe we don’t even force a user to have a name, just a user ID:

type User(id : string, name : string option) =
    new(id : string) = User(id, None)
    member x.Id = id
    member x.Name = name
type Session(user : User option) = 
    new() = Session(None)
    member x.User = user
type App(session : Session option) =
    new() = App(None)
    member x.Session = session

You walk the property tree like this:

let nameOpt = app.Session
              |> Option.bind (fun s -> s.User)
              |> Option.bind (fun u -> u.Name)
let name = defaultArg nameOpt "Guest"

Now if any property is None, from Session to User to Name, nameOpt is None, and name is "Guest".

Scala Saturday – The Option Type, Part 1

It’s like that time you played basketball in the living room. You knew you should never have done it. But it was just so tempting! And how did that work out for you? Broken lamp? Hole in the wall? And, if you grew up in a house like mine, a tanned hide to follow. You could have avoided it all: the property damage, the wounded pride, the tender backside.

That’s what playing with null is like. You know you shouldn’t, but it’s just so easy! Then you get burned in the end.

The Problem with Null

The problem with null is that it can crop up anywhere an object can. Consider a function that returns a string. This is always OK, right?

val foo: () => String = // ...
val len = foo().length // No worries?

It certainly is in this case:

val foo: () => String = () => "foo"
val len = foo().length
// len: Int = 3

But what about this?

val foo: () => String = () => null
val len = foo().length
// java.lang.NullPointerException !!!

Yeah, not so much. And the problem is that the compiler cannot help us: null is a perfectly legal return value.

We need better semantics! A return type of String ought to guarantee me that I get a String. An empty string would be fine; it just needs to be a String!

Even the guy who invented the concept of null has regretted it:

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler.

But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.

Sir Charles Antony Richard “Tony” Hoare
Turing Award Winner, Inventor of the Quicksort
Null References: The Billion Dollar Mistake (2009)

Fine! All this lamenting that null is a bad idea is great, but don’t you need a way to represent the idea that sometimes a function may not return a result, or at least, not what you would consider a valid result? That’s what Java maps do: If you call Map.get(key), and that map does not contain an entry for key, you get null. Of course, with most maps, null is a legal value, so you don’t know for certain whether null indicates whether the key was not found or the coder explicitly associated null with that key.

There’s got to be a better way!

Option to the Rescue

When you need to represent the idea that a function may not return a result, use Scala’s Option. You can think of an Option as a bucket (pronounced BUCK-et, not boo-KAY):

The Option type illustrated as a bucket. The bucket may be empty or full. If the Option contains a value (represented by the full bucket), we call it "Some." If the Option does not contain a value (represented by the empty bucket), we call it "None."
The Option Type: Is the Bucket Empty or Full?

When a function returns an Option[T], it may contain a value of type T; it may not. You don’t know until you look into it. It’s Schrödinger’s cat! If the Option is empty, we call it None. If it is full, we call it Some.

The advantage of using Option is that now the compiler can help you out. You cannot assign an Option[T] to a variable of type T. Take this example using List.find:

val opt = (1 to 4).toList.find(_ > 5)
val n : int = opt
// error: not found: type int
//        val n : int = opt

So then, you cannot forget and accidentally assign a null, only to have it bite you later. The compiler reminds you that you need to test the result before trying to use it:

val ns = (1 to 4).toList

val none = ns.find(_ > 5)

if (none.isEmpty) {
  println("None found greater than 5")
} else {
  println(s"Found one greater than 5: ${none.get}")
}
// None found greater than 5

val some = ns.find(_ < 5)
if (some.isEmpty) {
  println("None found less than 5")
} else {
  println(s"Found one less than 5: ${some.get}")
}
// Found one less than 5: 1

Of course, you can override the safeguard, but at least then, you cannot claim ignorance:

val ns = (1 to 4).toList
val none = ns.find(_ > 5)
println(s"Found one greater than 5: ${none.get}")
// java.util.NoSuchElementException: None.get !!!

Next week, we will look at Option some more to see how we can use it in a more functional fashion.