scala-logo-small

Prefer types over booleans

In a recent post I represented whether a TV was on or off as an enum in Java and case objects in Scala. Someone asked me why you would do either one when you could simply represent it as a boolean.

The same reasoning would seem to extend to any situation with two choices:

  1. Male/Female
  2. On/Off
  3. In/Out
  4. Active/Inactive
  5. Hot/Cold
  6. Light/Dark
  7. etc..

I have a rule:

prefer types over booleans

This post is about why.

Continue reading “Prefer types over booleans”

Why there aren’t enums in Scala

Why doesn’t Scala have enums like Java?

Java enums are a good solution for the wrong problem. Programmers who came to Java from C/C++ were sick of defining fixed sets of constants as integers and they reached for a solution that gave them the most obvious type-safe replacement. In other words, given an already-existing paradigm, they improved upon it, but they did not stop and rethink it.

You may not remember integer constants in C/C++. Let’s say a TV set had to have ON and OFF states. It would be represented somewhere as follows:

//C/C++
const int ON = 0;
const int OFF = 1;

And elsewhere:

private:
  int state = ON;

public:
 int getState() = {
   return state;
 }

“int getState?” But it should only return 0 or 1! There are no other states! We should not have ON/OFF represented with a type that allows for (generally) 2^32 states.

Given this state of affairs, Java’s language designers decided on the “enum” which looks like the following for the TV example:

enum TvState {
  ON, OFF
}
public class TV {

  private TVState state = TVState.OFF;

  public TvState getState() {
    return state;
  }
}

All of this makes perfect sense if fixed sets of integer constants has been your operating assumption for a number of years.

Except it isn’t…
Except there’s a definite amount of awkwardness that comes with Java enums.

For example, to define a method for the remote’s “Power” button, we need some way to check state. Java best practices are to use a switch statement for this, which is highlighted in this example:

public class TV {

  enum TVState { ON, OFF }

  private TVState state = TVState.OFF;

  public TVState getState() {
    return state;
  }

  public void power() {
    switch(state) {
      case ON: state = TVState.OFF; break;
      case OFF: state = TVState.ON; break;
    }
  }
}

It’s kind of annoying that you have to always say “TvState.whatever” even when “ON” and “OFF” are being used without the “TVState” prefix in the same line!!

If you forget that part then you’ll get a compilation error.

e.g. if your code is:

public void power() {
    switch(state) {
      case ON: state = OFF; break;
      case OFF: state = ON; break;
    }
  }

…it will trigger a compilation error:

TV.java:13: error: cannot find symbol
      case ON: state = OFF; break;
                       ^
  symbol:   variable OFF
  location: class TV
1 error

And that’s even though you are referring to “ON” and “OFF” right there in the same lines in your switch statement!!

But that’s not the most awkward thing…
No, that’s not the worst thing, at all, dear reader. The awkwardness is compounded the more your application complexity grows. Let’s say for the sake of example that the application is for running all the televisions in a sports bar. When you need to turn off all TVs in the bar the code needs to iterate all the TVs and find out if a particular TV is on or off. If it is on, then it should press the “power” button to turn it off.

Such code would look like this:

public void turnTvsOff(Collection<TV> tvs) {
    for(TV tv : tvs) {
      if(tv.getState() == TVState.ON) {
        tv.power();
      }
    }
  }

As you can see, to express the simple idea “turn TVs off” we end up with 3 lines of code that other programmers have to read (as highlighted above) before they can understand what is happening. And that’s in the simplest of examples.

How to handle it in Scala
Scala, on the other hand, doesn’t have enums. (There is something in Scala called an “Enumeration” but that’s a bit different and I won’t get into that here.)

Instead, it’s best to examine Scala’s type system directly, as it provides everything (and more) that Java’s enum types offered.

In Scala, you’d define an ADT for the TV state using “case objects.”

sealed trait TVState
case object ON extends TVState
case object OFF extends TVState

For the purposes of this conversation, Scala case objects are singletons with pattern matching capabilities built in.

Given the TVState ADT, code for finding out a TV’s state becomes less cluttered than the equivalent in Java:

case class TV(var state: TVState) {
  def power(): Unit = {
    state = state match {
      case ON => OFF
      case OFF => ON
    }
  }
}

Let me explain the power method line-by-line:

def power(): Unit = {
    state = state match {
      case ON => OFF
      case OFF => ON
    }
}

Line 1 declares the method as taking no parameters and returning “Unit” which is essentially Scala’s “void” type. It is a convention in Scala to define functions that alter mutable state with “()” parameters even though they aren’t required. By supplying the parameters you tell other Scala programmers that calling this function will have a side effect.

def power(): Unit = {
    state = state match {
      case ON => OFF
      case OFF => ON
    }
}

Line 2 shows the effect of the Scala idiom that “everything is an expression.” You can assign the results of if statements, pattern matches, etc. to variables. Here the “state” var gets reassigned to the result of a pattern match.

def power(): Unit = {
    state = state match {
      case ON => OFF
      case OFF => ON
    }
}

Lines 2-5 contain a pattern match. Since you are probably coming from Java think of pattern matches as Java’s switch statement on steroids. The steroids part doesn’t come into play at this point. Our example here is a very simple pattern match against constants (“state” matching either ON or OFF) which is very similar to Java’s switch statement. In a moment I will show a pattern match on steroids.

It’s important to back up right now and explain that how we defined TVState and its children ON and OFF has an effect on how the compiler can help with verifying the pattern match.

sealed trait TVState
case object ON extends TVState
case object OFF extends TVState

By adding the “sealed” keyword to the trait declaration the code closes off the possibility of any other file being able to add new classes or objects extending TVState. All TVState types must be defined in the same file where the sealed trait is declared. This helps both you and the compiler, since the compiler will now perform an exhaustiveness check on any pattern match. That means that if you leave out one of the children when pattern matching against a TVState value or variable, the compiler will warn you that you forgot something.

Now that this power method is defined, let’s rewrite the Java method “turnTVsOff” in Scala. To refresh your memory this is what it looks like:

public void turnTvsOff(Collection<TV> tvs) {
    for(TV tv : tvs) {
      if(tv.getState() == TVState.ON) {
        tv.power();
      }
    }
  }

Here is the Scala version:

def turnTvsOff(tvs: List[TV]): Unit = {
  tvs.collect {case t @ TV(ON) => t.power }
}

Here is our pattern match on steroids. In this one line of code, the simple idea “turn TVs off” is expressed in an almost direct way: collect TVs that match the constructor structure “TV(ON)” and press “power” on those instances. The constructor pattern match demonstrates how pattern matching in Scala is far more advanced than switch statements in Java.

Another feature of Scala’s pattern matching is the ability to name a matched structure, as shown here where we give the variable name “t” to the instances matching the pattern using the “@” syntax. (with the “t @” syntax). That is necessary here so that we can call the power method on the matched instances with the “t.power” statement. We could just as easily have used any variable name other than “t” — “tv”, “television”, “foo” — it doesn’t matter.

So why doesn’t Scala have enums?
Scala doesn’t have enums because it has stronger built-in capabilities than Java, which make enums unnecessary. There’s no need for a separate and awkward construct when types can be as simple or complex as you need them to be.

A postscript for the Java 8 fans
Astute readers of the blog will note that Java 8 provides functional constructs. Just to be clear, I want to point out that coding this example in Java 8 actually looks the same or worse than the Java 7 version, and is nowhere near as clean as the Scala version:

	tvs.stream()
           .filter(tv -> tv.getState() == TV.TVState.ON)
           .forEach(tv -> tv.power());

That’s still three lines of code, and we incur the overhead of turning the TVs list into a stream. In more complex examples, which I plan to write about later on this site, Java 8 functional constructs start losing a big battle to Scala precisely because Java 8 provides no pattern matching capability. They also scale poorly due to being put on top of a non-unified type system. An example I recently hit is when retrieving a collection that was a member of a class (e.g. myObject.getSomeCollection()) the Java 8 functional way to flatMap that collection into something that can be iterated is to have a whole separate call for it like “flatMap(Set::stream)”.

In Scala, if you perform a flatMap on a collection it is automatically available to the next functional call in the chain.

scala-logo-small

Scala permutation generation shootout – for-comprehension vs. functional style

Today’s entry is about generating permutations in both a functional and readable way.

No, these qualities are not at odds with each other. At least, they don’t have to be.

The example code today generates permutations where r = n. For example, given List(1,2,3) (n = 3, the size of the list) how many permutations of length 3 (r = 3 also) are there.

See the difference…

pins3Cover185x240

Programming in Scala, 3rd Edition, or you’re out of date!

At this time there is only one book covering Scala 2.12, and that is Programming in Scala, Third Edition by Odersky, Spoon, and Venners. It was released this past April. I have been running across recommendations for other Scala books and while those are good, this is the one book everyone who touches Scala must have. Even though I’ve referenced second edition numerous times, I bought third edition immediately and have been reading through it. I think I’m about half way through right now.

Get CODE in your inbox

Yes email me when there are new posts