September 3, 2014
Originally posted at Underscore.
Should you use Scala's built in
scala.Enumerationclass, or roll your own sealed class objects? The answer depends on which you value more: having a single lightweight class, or better type safety.
If you want to skip the detail, just know to use
scala.Enumerationif you need to limit the number of classes; otherwise prefer case objects or classes.
The rest of this post describes:
- the problem with Enumeration;
- the benefits of Enumeration; and
- the alternatives you can use.
What's the problem with scala.Enumeration?
"Enumerations must D.I.E." (thread on scala-internals mailing list)
Here are the main criticisms I've seen of
scala.Enumeration(which I'll mostly just refer to as Enumeration from now on):
- Enumerations have the same type after erasure.
- There's no exhaustive matching check during compile.
- They don't inter-operate with Java's
If 3 is your main concern, just use Java's
enums. You can mix Java and Scala source files in a project.
Points 1 and 2 deserve examples, so you can decide if you care about this behaviour or not.
First, if you want method overloading with different Enumerations, that's not going to work out:
Second, if you want to use Enumeration in pattern matching, you will not get a "match may not be exhaustive" warning:
Note: the compiler is happy to accept that, even though the function can fail at runtime with a
You may or may not care about those points.
What is an Enumeration?
For me, I'd expect an Enumeration to not have the problems listed above. This is fine, because Scala allows me to look at enumerations another way, which we will see in a moment.
scala.Enumeration, look at it with a different view:
I really think that enums should be lightweight. One class (or even two) per value is not acceptable. If you are willing to pay that sort of price, it's not too burdensome to just define the case objects directly. Enums fill a different niche: essentially as efficient as integer constants but safer and more convenient to define and to use. (Martin on the scala-internals mailing list)
Under that view, you can see how Enumeration gives you plenty of positives:
- Values have an automatic identifier, which is a consecutive integer.
- Values have an nice name, which you don't have to declare yourself.
- Enumerations have an order (
Mon < Tueis
- You can iterate the members.
- You do not end up with a class per member.
Except for the last point, you can have everything via a sealed case objects. This is why we say it's the key deciding point on using
Sealed case objects
The alternative can be as simple or as involved as you need it to be for your problem.
As an example, let's say you're happy building up the list of values yourself, don't care about order or automatic naming:
That's a minimal example. You can then build anything extra you need. To illustrate, here's the Oracle Java Planets enum example converted to this style:
This version has an ordered enumeration, and uses a macro to generate the set of all values.
You don't need macros to achieve this. The set of enumeration values can be automatically populated in a parent class of your enumeration. A good example of this is the Viktor Klang "DIY Enum". I've also made the long Oracle Planets example of the DIY Enum available as a gist, and all the code in this post is available in a git repository.
scala.Enumerationhas a particular view of what it means to be an enumeration. Use it where it fits your view of an enumeration.
A sealed set of case objects is a good way to represent an enumeration. You can make this as simple or as sophisticated as you need for your project.
January 5, 2014
At the end of last year I had some fun implementing a CRDT. These are data structures designed to combine together when you have no control over order of changes, timing of changes, or the number of participants in the data structure. The example I looked at was a sequential datatype, namely the WOOT CRDT for collaborative text editing.
Before you do that, you might want to watch my colleague Noel's talk on Reconciling Eventually-Consistent Data with CRDTs which was, not coincidently, right before mine.
If you find yourself looking at a network and thinking "how can I reliably combine these things?" without global synchronised clocks, do have a look at CRDTs because they are #fun and #interesting.
July 24, 2013
Most of my writing effort has gone into The Lift Cookbook, and one thing I missed was why you might be interested in Lift.
That's now fixed, via a three-part series of short posts over at programming.oreilly.com:
Hope you find the framework as fun and productive as I do.
The Lift Cookbook in PDF, on Kindle, print, via the Play Bookstore, and in iBooks.