The Preface was the last chapter I wrote in the Scala Cookbook. Initially I didn’t plan to write a Preface for the book, but I was more or less told by my editor that it was mandatory. So I waited until I finished the rest of the book before starting on it. To me that made sense; I couldn’t write a decent Preface without knowing the final contents of the book. Sure, I wrote small notes for the Preface throughout the book-writing process, but I didn’t try to put those into final thoughts until the rest of the book was finished.
I wrote several different versions of the Preface, condensed them into one, and then rewrote it more than ten times over ten days, ending up with the content shown below. On most days I’d write/edit it in the morning, print it, then sit at McDonald’s or Starbucks in the afternoon, hand-edit the printed copy, then come home and type the changes. After that, I’d avoid it the rest of the evening so it would seem “fresh” the following morning. Finally, I let it sit over the last weekend, read it once more on Monday, June 3, 2013, made a few last changes, and then sent it in to my editor. At that point I thought the book was “done”, except for the final process of working with an O’Reilly copyeditor.
(Boy, was I wrong.)
Before getting to the Preface, one more thing: My editor deleted the “What I Like Best” section, which I’ve included below. She removed it not because of the content, but because of her concerns about the length of the book.
Given that background, here’s the original Preface to the Scala Cookbook.
Preface
This is a cookbook of problem-solving recipes about Scala, the most interesting programming language I’ve ever used. The book contains solutions to more than 300 common problems, shown with possibly more than 1,000 examples. (I haven’t counted, but I suspect that’s true.)
There are a few unique things about this book:
- As a cookbook, it’s intended to save you time by providing solutions to the most common problems you’ll encounter.
- Almost all of the examples are shown in the Scala interpreter, or REPL (“Read-Eval-Print-Loop”). As a result, whether you’re sitting by a computer, on a plane, or reading in your favorite recliner, you get the benefit of seeing their exact output. (Which often leads to, “Ah, so that’s how that works.”)
- The book covers not only the Scala language, but also has large chapters on Scala tools and libraries, including SBT, actors, the collections library, TDD- and BDD-style testing, JSON processing, and the Play Framework.
Just prior to its release, the book was updated to cover Scala 2.10.x, SBT 0.12.3, and Play 2.1.x.
The Scala language
My (oversimplified) Scala elevator pitch is that it’s a child of Ruby and Java: it’s light, concise, and readable like Ruby, but it compiles to class files that you package as JAR files that run on the JVM; it uses traits and mixins, and feels dynamic, but it’s statically typed. It uses the Actor model to simplify concurrent programming so you can keep those multicore processors humming. The name Scala comes from the word scalable, and true to that name, it’s used to power the busiest websites in the world, including Twitter, Netflix, Tumblr, LinkedIn, Foursquare, and many more.
In my opinion, Scala is not a good language for teaching a Programming 101 class. Instead, it’s a power language created for the professional programmer. Don’t let that scare you, though. If you were my own brother and about to start a new project and could choose any programming language available, without hesitation I’d say, “Use Scala.”
Here are a few more nuggets about Scala:
- It’s a modern programming language created by Martin Odersky (the father of javac), influenced by Java, Ruby, Smalltalk, ML, Haskell, Erlang, and others.
- It’s a pure object-oriented programming (OOP) language. Every variable is an object, and every “operator” is a method.
- It’s also a functional programming (FP) language, so you can pass functions around as variables. You can write your code using OOP, FP, or both.
- Scala code runs on the JVM and lets you use the wealth of Java libraries that have been developed over the years.
- You can be productive on Day 1, but the language is deep, so as you go along you’ll keep learning, and finding newer, better ways to write code. Scala will change the way you think about programming (and that’s a good thing).
Of all of Scala’s benefits, what I like best is that it lets you write concise, readable code. The time a programmer spends reading code compared to the time spent writing code is said to be at least a 10:1 ratio, so writing code that’s concise and readable is a big deal. Because Scala has these attributes, programmers say that it’s expressive.
What I like best
Of all of Scala’s benefits, what I like best is that it lets you write concise, readable code. The time a programmer spends reading code compared to the time spent writing code is said to be at least a 10:1 ratio, so writing code that’s both concise and readable is a big deal.
More than just expressive, Scala feels like a light, dynamic scripting language. For instance, Scala’s type inference system eliminates the need for the obvious. Rather than always having to specify types, you simply assign your variables to their data:
val hello = "Hello, world" // a String val i = 1 // an Int val x = 1.0 // a Double
Notice that there’s no need to declare that a variable is a String
, Int
, or Double
. This is Scala’s type inference system at work.
The rest of the language feels similarly light, and as a result, I suspect any experienced developer can understand this code:
case class Person (var name: String) val p = Person("Jonathan Stuart Leibowitz") p.name = "Jon Stewart" // name change println(p.name)
As your code gets more complicated, Scala’s expressiveness lets you say a lot while writing a little:
val friends = List(Person("adam"), Person("bill"), Person("kim")) friends.foreach(f => println(f.name))
“Sure,” you say, “I can read that. But how about something more difficult?” Okay, how about a for
loop with a few embedded if
statements:
for { f <- friends if f.name != "adam" if f.name.length < 4 } println(f.name.capitalize)
That’s still very readable, isn’t it?
Even building concurrent applications seems downright simple. Scala is well-known for including an industrial-strength Actor library for writing concurrent applications, so that must be difficult, right? Let’s see ...
Imagine that you have an actor named car
, and you want to start it. How do you do that? Send it a message. While you’re at it, go ahead and open the garage door, too:
car ! Start garage ! OpenDoor
Lest you think writing an actor is hard, fear not. Just implement the startCar
method in the following Car
actor, and you’re in business:
class Car extends Actor { def receive = { case Start => startCar case Stop => stopCar } def startCar { // code to start the car } }
I could go on for some time -- another 800 pages or so -- but for the moment, I’m sure you see that Scala is a light, expressive language.
Solutions
I’ve always bought O’Reilly cookbooks for the solutions, and that’s what this book is about: solving problems.
When using a cookbook, I usually think, “I have this problem, I need to iterate over the elements in an Array, what’s the best way to do that?” I like to look at the table of contents, find a recipe, implement the solution, and move on. I tried to write each recipe with this use case in mind.
However, with a modern language like Scala, it may end up that I phrased my question wrong. Because of my prior programming experience I may have thought, “I need to iterate over the elements in an Array,” but in reality my deeper intent was to loop over those elements for a reason, such as to transform them into a new collection. So it’s nice when a recipe says, “Hey, I know you’re here to read about how to loop over the elements in an Array
, here’s how you do that”:
for (i <- List(1,2,3)) println(i)
“But, if what you’re really trying to do is transform those elements into a new collection, what you want is a for/yield expression or map method”:
// for/yield scala> for (i <- List(1,2,3)) yield i * 2 res0: List[Int] = List(2, 4, 6) // map scala> List(1,2,3).map(_ * 2) res1: List[Int] = List(2, 4, 6)
(More on that _ character shortly.)
To create the list of problems and solutions, I followed the “Eat your own dog food” philosophy. The recipes come from my own experience of creating Scala scripts, web applications, web services, Swing applications, and actor-based systems. As I developed the applications I needed, I encountered problems like these:
- Scala files tend to be very small; what’s the proper way to organize an application?
- It looks like SBT is the best build tool for Scala, but it’s different than Ant or Maven; how do I compile and package applications, and work with dependencies?
- Constructors are really different than Java; how do I create them? What code is generated when I declare constructor parameters and class fields?
- Actors are cool; how do I write a complete actor-based application?
- What, I shouldn’t use null values any more? Why not? How do I code without them?
- I can pass a function around like any other variable? How do I do that, and what’s the benefit?
- Why are there so many collections classes, and why does each collection class have so many methods?
- I have all of this legacy Java code; can I still use it in Scala? If so, how?
- I’m starting to grok this. Now I need to know, what are the top five or ten “best practices” of writing Scala code?
Truthfully, I fell fast in love with everything about Scala except for one thing: the collections library seemed large and intimidating. I really enjoyed using Scala so I kept using the language, but whenever I needed a collection, I used a trusty old Java collection.
Then one day I got up the courage to dive into the collections library. I thought I’d hate it, but after struggling with it for a while, I suddenly “got” it. The light bulb went on over my head, and I suddenly understood not only the collections, but several other concepts I had been struggling with as well. I realized the collections library writers aren’t crazy; they’re brilliant.
Once I understood the collections library, I quit writing so many for
loops, and started using collection methods like filter
, foreach
, and map
. They made coding easier, and made my code more concise. These days I can’t imagine a better way to write code like this:
// filter the items in a list scala> val nums = List(1,2,3,4,5).filter(_ < 4) nums: List[Int] = List(1, 2, 3)
The _ wildcard character is discussed in several recipes, but as you can infer from that example, it’s a placeholder for each element in the collection. The filter
method loops through each element in the list, calling your _ < 4
function on each iteration. That Scala one-liner shown is the equivalent of this Java code:
// java Integer[] intArray = {1,2,3,4,5}; List<Integer> nums = Arrays.asList(intArray); List<Integer> filteredNums = new LinkedList<Integer>(); for (int n: nums) { if (n < 4) filteredNums.add(n); }
The next example takes this a step further. It filters the elements as in the previous example, and then multiplies each element by the number 2
using the map
method:
// filter the items, then double them scala> val nums = List(1,2,3,4,5).filter(_ < 4).map(_ * 2) nums: List[Int] = List(2, 4, 6)
If you think about how much code would be required to write that last expression in another language, I think you’ll agree that Scala is expressive.
(If you’re new to Scala, examples like this are broken down into smaller chunks in the recipes.)
The End
There’s more to the original Scala Cookbook Preface, but because the book was edited down from the initial 23 chapters down to 20 chapters (because the book was almost 900 pages long), I haven’t posted the original “Contents of this Book” section, to avoid confusion.
If you like the Preface, I hope you’ll like the rest of the Scala Cookbook. Here’s a link to it on Amazon:
All the best,
Al