Preface
This is a cookbook of problem-solving recipes about Scala 3, the most interesting programming language I’ve ever used. The book contains solutions to more than two hundred fifty common Scala programming problems, demonstrated with more than one thousand examples.
Compared to other Scala 3 learning resources, there are several 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.
-
The book covers not only the Scala language but also recipes on Scala tools and libraries, including sbt, Spark, Scala.js, Akka actors, and JSON processing with the Play Framework.
-
The book takes a big dive into the Scala collections classes, using five chapters to demonstrate their use.
-
Output from the examples is shown either in the Scala interpreter or in comments after the code. 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 Scala 3 Language
In the first edition of Scala Cookbook, I described Scala 2 as feeling like a combination of Ruby and Java. Back then I wrote, “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 Java virtual machine (JVM); it uses traits and mixins, and feels dynamic, but it’s statically typed.”
Since then, the Scala language features have been rethought and debated in an open, public process, and with the release of Scala 3 in 2021, the language feels even lighter, and now it seems like a combination of four terrific languages: Ruby and Java, combined with the lightweight and clean syntax of Python and Haskell.
Part of this even-lighter feel is thanks to the new optional braces syntax, which is also known as a significant indentation style. With this one change, for
loops that used to look like this:
for
(
i
<-
1
to
5
)
{
println
(
i
)
}
now look like this:
for
i
<-
1
to
5
do
println
(
i
)
Similarly, if
expressions and many other expressions also use less boilerplate syntax and are easier to read:
val
y
=
if
(
x
==
1
)
{
true
}
else
{
false
}
// Scala 2
val
y
=
if
x
==
1
then
true
else
false
// Scala 3
While this new syntax is considered optional, it’s become the de facto standard and is used in this book, the Scala 3 Book that I cowrote for the Scala documentation website, the official Scala 3 training classes on Coursera, the books Programming in Scala by Martin Odersky et al. (Artima Press) and Programming Scala by Dean Wampler (O’Reilly), and many more learning resources.
The new syntax isn’t the only change. Scala 3 has many new features, including:
-
Enumerations
-
Union and intersection types
-
Top-level definitions (so your code no longer has to be contained inside classes, traits, and objects)
-
Simplified use of implicits with the new
given
andusing
syntax -
Greatly simplified syntax for extension methods and type classes
Even the syntax of traits and classes has been simplified to be more readable than ever before:
trait
Animal
:
def
speak
():
Unit
trait
HasTail
:
def
wagTail
():
Unit
class
Dog
extends
Animal
,
HasTail
:
def
speak
()
=
println
(
"Woof"
)
def
wagTail
()
=
println
(
"⎞⎜⎛ ⎞⎜⎛"
)
With the new syntax, every construct that creates unnecessary “noise” in your code has been removed.
Scala Features
In addition to everything just stated, Scala provides a multitude of features that make it a unique and truly modern programming language:
-
It’s created by Martin Odersky—the “father” of
javac
—and influenced by Java, Ruby, Smalltalk, ML, Haskell, Python, Erlang, and others. -
It’s a high-level programming language.
-
It has a concise, readable syntax—we call it expressive.
-
It’s statically typed—so you get to enjoy all the benefits of static type safety—but it feels like a dynamic scripting language.
-
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.
-
Indeed, the essence of Scala is, as Mr. Odersky puts it, that it’s a fusion of FP and OOP in a typed setting, with:
-
Functions for the logic
-
Objects for the modularity
-
-
It runs on the JVM, and thanks to the Scala.js project, it’s also a type-safe JavaScript replacement.
-
It interacts seamlessly with Java and other JVM libraries.
-
Thanks to GraalVM and Scala Native, you can now create fast-starting native executables from your Scala code.
-
The innovative Scala collections library has dozens of prebuilt functional methods to save you time and greatly reduces the need to write custom
for
loops and algorithms. -
Programming best practices are built into Scala, which favors immutability, anonymous functions, higher-order functions, pattern matching, classes that cannot be extended by default, and much more.
-
The Scala ecosystem offers the most modern FP libraries in the world.
One thing that I love about Scala is that if you’re familiar with Java, you can be productive with Scala 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.
Scala Feels Light and Dynamic
More than just being 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.
Creating your own custom types works in exactly the same way. Given a Person
class:
class
Person
(
val
name
:
String
)
you can create a single person:
val
p
=
Person
(
"Martin Odersky"
)
or multiple people in a list, with no unnecessary boilerplate code:
val
scalaCenterFolks
=
List
(
Person
(
"Darja Jovanovic"
),
Person
(
"Julien Richard-Foy"
),
Person
(
"Sébastien Doeraene"
)
)
And even though I haven’t introduced for
expressions yet, I suspect that any developer with a little bit of experience can understand this code:
for
person
<-
scalaCenterFolks
if
person
.
name
.
startsWith
(
"D"
)
do
println
(
person
.
name
)
And even though I haven’t introduced enums yet, the same developer likely knows what this code means:
enum
Topping
:
case
Cheese
,
Pepperoni
,
Mushrooms
,
Olives
Notice again that there’s no unnecessary boilerplate code here; the code is as “minimalist” as possible, but still easily readable. Great care has been taken to continue Scala’s tradition of being an expressive language.
In all of these examples you can see Scala’s lightweight syntax, and how it feels like a dynamic scripting language.
Audience
This book is intended for programmers who want to be able to quickly find solutions to problems they’ll encounter when using Scala and its libraries and tools. I hope it will also be a good tool for developers who want to learn Scala. I’m a big believer in learning by example, and this book is chock-full of examples.
I generally assume that you have some experience with another programming language like C, C++, Java, Ruby, C#, PHP, Python, Haskell, and the like. My own experience is with those languages, so I’m sure my writing is influenced by that background.
Another way to describe the audience for this book involves looking at different levels of software developers. In this article on Scala levels, Martin Odersky defines the following levels of computer programmers:
-
Level A1: Beginning application programmer
-
Level A2: Intermediate application programmer
-
Level A3: Expert application programmer
-
Level L1: Junior library designer
-
Level L2: Senior library designer
-
Level L3: Expert library designer
This book is primarily aimed at the application developers in the A1, A2, A3, and L1 categories. While helping those developers is my primary goal, I hope that L2 and L3 developers can also benefit from the many examples in this book―especially if they have no prior experience with functional programming, or they want to quickly get up to speed with Scala and its tools and libraries.
Contents of This Book
This book is all about solutions, and Chapter 1, Command-Line Tasks contains a collection of recipes centered around using Scala at the command line. It begins by showing tips on how to use the Scala REPL, as well as the feature-packed Ammonite REPL. It then shows how to use command-line tools like scalac
and scala
to compile and run your code, as well as the javap
command to disassemble your Scala class files. Finally, it shows how to run Scala-generated JAR files.
Chapter 2, Strings provides recipes for working with strings. Scala gets its basic String
functionality from Java, but with the power of implicit conversions, Scala adds new functionality to strings, so you can also treat them as a sequence of characters (Char
values).
Chapter 3, Numbers and Dates provides recipes for working with Scala’s numeric types, as well as the date classes that were introduced with Java 8. In the numeric recipes, you’ll see that there are no ++ and –– operators for working with numbers; this chapter explains why and demonstrates the other methods you can use. It also shows how to handle large numbers, currency, and how to compare floating-point numbers. The date recipes use the Java 8 date classes and also show how to work with legacy dates.
Chapter 4, Control Structures demonstrates Scala’s built-in control structures, starting with if/then statements and basic for
loops, and then provides solutions for working with for/yield loops (for
comprehensions), and for
expressions with embedded if
statements (guards). Because match
expressions and pattern matching are so important to Scala, several recipes show how to use them to solve a variety of problems.
Chapter 5, Classes provides examples related to Scala classes, parameters, and fields. Because Scala constructors are very different than Java constructors, several recipes show the ins and outs of writing both primary and auxiliary constructors. Several recipes show what case
classes are and how to use them.
Chapter 6, Traits and Enums provides examples of the all-important Scala trait, as well as the brand-new enum
. The trait recipes begin by showing how to use a trait like a Java interface, and then they dive into more advanced topics, such as how to use traits as mixins, and how to limit which members a trait can be mixed into using a variety of methods. The final two recipes demonstrate how to use enums in domain modeling, including the creation of algebraic data types (ADTs).
Chapter 7, Objects contains recipes related to objects, including the meaning of an object as an instance of a class, as well as everything related to the object
keyword.
Chapter 8, Methods shows how to define methods to accept parameters, return values, use parameter names when calling methods, set default values for method parameters, create varargs fields, and write methods to support a fluent style of programming. The last recipe in the chapter demonstrates the all-new Scala 3 extension methods.
Chapter 9, Packaging and Imports contains examples of Scala’s package
and import
statements, which provide more capabilities than the same Java keywords. This includes how to use the curly brace style for packaging, how to hide and rename members when you import them, and more.
Although much of the book demonstrates FP techniques, Chapter 10, Functional Programming combines many FP recipes in one location. Solutions show how to define anonymous functions (function literals) and use them in a variety of situations. Recipes demonstrate how to define a method that accepts a function argument, partially applied functions, and how to return a function from a function.
The Scala collections library is rich and deep, so Chapters 11 through 15 provide hundreds of collection-related examples.
Recipes in Chapter 11, Collections: Introduction help you choose collections classes for specific needs and then help you choose and use methods within a collection to solve specific problems, such as transforming one collection into a new collection, filtering a collection, and creating subgroups of a collection.
Chapter 12, Collections: Common Sequence Classes demonstrates the most common collections classes, including Vector
, List
, ArrayBuffer
, Array
, and LazyList
. Recipes demonstrate how to create each type, as well as adding, updating, and removing elements.
Chapter 13, Collections: Common Sequence Methods then demonstrates how to use the most common methods that are available for the Scala sequence classes. Recipes show how to iterate over sequences, transform them, filter them, sort them, and more.
In the same way that the previous chapter demonstrates common sequence methods, Chapter 14, Collections: Using Maps demonstrates many of the same techniques for use with Scala Map
classes.
Lastly, Chapter 15, Collections: Tuple, Range, Set, Stack, and Queue provides coverage of the other Scala collections classes, including tuples, ranges, sets, stacks, and queues.
Chapter 16, Files and Processes then shows how to work with files and processes. Recipes demonstrate how to read and write files, obtain directory listings, and work with serialization. Several recipes then demonstrate how to work with external processes in a platform-independent manner.
Chapter 17, Building Projects with sbt is a comprehensive guide to the de facto build tool for Scala applications. It starts by showing several ways to create an sbt project directory structure, and then it shows how to include managed and unmanaged dependencies, build your projects, generate Scaladoc for your projects, deploy your projects, and more.
Chapter 18, Concurrency with Scala Futures and Akka Actors provides solutions for the wonderful world of building concurrent applications (and engaging those multicore CPUs!) with futures and the Akka actors library. Recipes with futures show how to build one-shot, short-lived pockets of concurrency, while the actors’ recipes demonstrate how to create long-living parallel processes that may respond to billions of requests in their lifetime.
Chapter 19, Play Framework and Web Services shows how to use Scala on both the client and server sides of web services. On the server side it shows how to use the Play Framework to develop RESTful web services. For both client and server code it shows how to serialize and deserialize JSON, and how to work with HTTP headers.
Chapter 20, Apache Spark demonstrates the Apache Spark framework. Spark is one of the applications that made Scala famous, and recipes demonstrate how to work with large datasets as a Resilient Distributed Dataset (RDD), and also how to query them using industry-standard SQL queries.
Chapter 21, Scala.js, GraalVM, and jpackage provides several recipes for libraries and tools in the Scala and JVM worlds. The first several recipes demonstrate how to use Scala.js as a type-safe JavaScript replacement. The final recipes show how to convert your Scala code into a native executable using GraalVM, and then how to package your Scala application as a native application using Java’s jpackage
utility.
Chapter 22, Integrating Scala with Java shows how to solve the few problems you might encounter when integrating Scala and Java code. While Scala code often just works when interacting with Java, there are a few “gotchas.” This chapter shows how to resolve problems related to the differences in the collections libraries, as well as problems you can run into when calling Scala code from Java.
Chapter 23, Types provides recipes for working with Scala’s powerful type system. Starting right from the introduction, concepts such as type variance, bounds, and constraints are demonstrated by example. Recipes show how to declare generics in class and method definitions, implement duck typing, and control which types your traits can be mixed into. Then several all-new Scala 3 concepts are demonstrated with opaque types, given`and `using
values as a replacement for implicits, union and intersection types, and two recipes related to the concept of equality when comparing objects.
Chapter 24, Best Practices is unique for a cookbook, but because this is a book of solutions, I think it’s important to have a section dedicated to showing the best practices, i.e., how to write code “the Scala way.” Recipes show how to create methods with no side effects, how to work with immutable objects and collection types, how to think in terms of expressions (rather than statements), how to use pattern matching, and how to eliminate null values in your code.
Installing Scala
You can install Scala 3 in several different ways, including Homebrew (on macOS), Coursier, SDKMAN, and downloading and installing Scala manually. Coursier is considered to be the “Scala installer,” and its use is covered in this “Getting Started with Scala 3” page.
If you don’t want to install Scala just yet, you can also experiment with it in your browser using these online tools:
Conventions in This Book
There are a few important points to know about the conventions I use in this book. First, as mentioned, I use the optional braces (significant indentation) programming style, which eliminates most need for parentheses and curly braces:
for
i
<-
1
to
5
do
println
(
i
)
// use this style
for
(
i
<-
1
to
5
)
{
println
(
i
)
}
// don’t use this style
Along with this style, I indent my code with four spaces. Currently there’s no indentation standard, and developers seem to prefer two to four spaces.
Next, when I show examples, I often show the result of my examples in comments after the examples. Therefore, my examples look like this:
(
1
to
10
by
2
).
toList
// List(1, 3, 5, 7, 9)
(
1
until
10
by
2
).
toList
// List(1, 3, 5, 7, 9)
(
'd'
to
'h'
).
toList
// List(d, e, f, g, h)
(
'd'
until
'h'
).
toList
// List(d, e, f, g)
Using this style helps me include many more examples in this book than I could fit in the first edition.
Other coding standards used in this book are:
-
I always define variables as
val
fields (which are likefinal
in Java), unless there’s a reason they need to be avar
. -
When a method takes no parameters and has a side effect (such as printing to the console), I define and call the method with empty parentheses, as
()
. -
While in many situations it’s not necessary to define data types, I always declare the return type of public methods.
As an example of that last standard, you can define a method without declaring its return type, like this:
def
double
(
i
:
Int
)
=
i
*
2
However, most developers prefer to show the method return type:
def
double
(
i
:
Int
):
Int
=
i
*
2
For just a few more characters of typing now, it makes your code easier to read later.
Support
Many of the source code examples shown in this book are available in this GitHub repository, which includes many complete sbt projects:
The Scala Gitter channel is an excellent source of help, and you’ll occasionally see my questions out there.
If you’re interested in proposals and debates about Scala features, the “Scala Contributors” website is also a terrific resource.
Finally, you can find my latest blog posts at alvinalexander.com, and I often tweet about Scala topics at twitter.com/alvinalexander.
Conventions Used in This Book
The following typographical conventions are used in this book:
- Italic
-
Indicates new terms, URLs, email addresses, filenames, and file extensions.
Constant width
-
Used for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords.
Constant width italic
-
Shows text that should be replaced with user-supplied values or by values determined by context.
Tip
This element signifies a tip or suggestion.
Note
This element signifies a general note.
Warning
This element indicates a warning or caution.
Using Code Examples
Supplemental material (code examples, exercises, etc.) is available for download at https://github.com/alvinj/ScalaCookbook2Examples.
If you have a technical question or a problem using the code examples, please send an email to bookquestions@oreilly.com.
This book is here to help you get your job done. In general, if example code is offered with this book, you may use it in your programs and documentation. You do not need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product’s documentation does require permission.
We appreciate, but generally do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “Scala Cookbook by Alvin Alexander (O’Reilly). Copyright 2021 Alvin Alexander, 978-1-492-05154-1.”
If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at permissions@oreilly.com.
O’Reilly Online Learning
Note
For more than 40 years, O’Reilly Media has provided technology and business training, knowledge, and insight to help companies succeed.
Our unique network of experts and innovators share their knowledge and expertise through books, articles, and our online learning platform. O’Reilly’s online learning platform gives you on-demand access to live training courses, in-depth learning paths, interactive coding environments, and a vast collection of text and video from O’Reilly and 200+ other publishers. For more information, visit http://oreilly.com.
How to Contact Us
Please address comments and questions concerning this book to the publisher:
- O’Reilly Media, Inc.
- 1005 Gravenstein Highway North
- Sebastopol, CA 95472
- 800-998-9938 (in the United States or Canada)
- 707-829-0515 (international or local)
- 707-829-0104 (fax)
We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at https://oreil.ly/scala-cookbook-2e.
Email bookquestions@oreilly.com to comment or ask technical questions about this book.
For news and information about our books and courses, visit https://oreilly.com.
Find us on Facebook: https://facebook.com/oreilly
Follow us on Twitter: https://twitter.com/oreillymedia
Watch us on YouTube: https://youtube.com/oreillymedia
Acknowledgments
Writing a book this large takes a lot of work, and I’d like to thank my editor, Jeff Bleiel, for his work throughout the creation of this book. We began working together on the book in December 2018, and while Scala 3 kept changing through the community process, we continued working together on it until the book’s completion in 2021.
As I completed initial drafts of chapters, Jeff offered hundreds of suggestions on how to improve them. This process continued on through the COVID-19 pandemic, and as the book became more clear, Jeff (correctly) suggested the reorganization of several chapters. He’s incredibly thorough, and I can tell you that when you see a book that’s been edited by Jeff Bleiel, you can be assured that it’s well edited and thought out.
For this edition of the book, all the reviewers were helpful in different ways. Jason Swartz was a “most valuable reviewer” candidate on the first edition of Scala Cookbook, and he did another stellar job on this edition with many solid suggestions.
Philip Schwarz joined us on this edition and offered a number of good insights, especially on the early chapters of the book.
But for this edition, I owe a huge and special thanks to Hermann Hueck, who was the most valuable reviewer for this edition. Hermann offered hundreds of suggestions, both large and small, covering everything from the smallest line of code to the overall organization of the book.
I can’t say enough about both Jeff and Hermann, but maybe the best way to say it is that this book wouldn’t have been the same without them—thank you both!
I’d also like to thank Christopher Faucher, the production editor for this book. After Jeff and I agreed that we were finished with the initial writing and editing process, Chris came in and helped get the book to the finish line, as we worked through hundreds of comments and issues. If you know what it’s like to bring a large software application to life, getting a big book like this past the finish line is exactly the same. Thank you, Chris!
Finally, I’d like to thank Martin Odersky and his team for creating such an interesting programming language. I first fell in love with Scala when I found his book Programming in Scala at a bookstore in Anchorage, Alaska, in 2010, and since then it’s been a lovefest that continues through Scala 3 in 2021 and beyond.
All the best,
Al
Get Scala Cookbook, 2nd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.