Get Object Orientation Abstraction and Data Structures Using Scala 2nd Edition Edition Mark C. Lewis PDF ebook with Full Chapters Now
Get Object Orientation Abstraction and Data Structures Using Scala 2nd Edition Edition Mark C. Lewis PDF ebook with Full Chapters Now
https://ebookultra.com
https://ebookultra.com/download/object-
orientation-abstraction-and-data-structures-using-
scala-2nd-edition-edition-mark-c-lewis/
https://ebookultra.com/download/objects-abstraction-data-structures-
and-design-using-c-1st-edition-elliot-b-koffman/
ebookultra.com
https://ebookultra.com/download/data-structures-and-problem-solving-
using-c-2nd-international-edition-edition-mark-allen-weiss/
ebookultra.com
https://ebookultra.com/download/data-structures-using-c-c-2nd-edition-
edition-aaron-m-tenebaum/
ebookultra.com
https://ebookultra.com/download/data-structures-using-c-1st-edition-
patil/
ebookultra.com
Data Abstraction Problem Solving with C 6th Edition Frank
M. Carrano
https://ebookultra.com/download/data-abstraction-problem-solving-
with-c-6th-edition-frank-m-carrano/
ebookultra.com
https://ebookultra.com/download/data-structures-and-problem-solving-
using-java-4th-intern-edition-weiss/
ebookultra.com
https://ebookultra.com/download/data-structures-and-algorithms-using-
python-1st-edition-rance-d-necaise/
ebookultra.com
https://ebookultra.com/download/java-methods-object-oriented-
programming-and-data-structures-third-ap-3rd-ap-edition-maria-litvin/
ebookultra.com
https://ebookultra.com/download/data-structures-a-pseudocode-approach-
with-c-2nd-edition-richard-f-gilberg/
ebookultra.com
Object Orientation Abstraction and Data Structures
Using Scala 2nd Edition Edition Mark C. Lewis Digital
Instant Download
Author(s): Mark C. Lewis; Lisa L. Lacher
ISBN(s): 9781498732161, 149873216X
Edition: 2nd Edition
File Details: PDF, 5.97 MB
Year: 2016
Language: english
OBJECT-ORIENTATION,
ABSTRACTION, AND
DATA STRUCTURES
USING
SCALA
SECOND EDITION
CHAPMAN & HALL/CRC
TEXTBOOKS IN COMPUTING
Series Editors
This series covers traditional areas of computing, as well as related technical areas, such as
software engineering, artificial intelligence, computer engineering, information systems, and
information technology. The series will accommodate textbooks for undergraduate and gradu-
ate students, generally adhering to worldwide curriculum standards from professional societ-
ies. The editors wish to encourage new and imaginative ideas and proposals, and are keen to
help and encourage new authors. The editors welcome proposals that: provide groundbreaking
and imaginative perspectives on aspects of computing; present topics in a new and exciting
context; open up opportunities for emerging areas, such as multi-media, security, and mobile
systems; capture new developments and applications in emerging fields of computing; and
address topics that provide support for computing, such as mathematics, statistics, life and
physical sciences, and business.
Published Titles
OBJECT-ORIENTATION,
ABSTRACTION, AND
DATA STRUCTURES
USING
SCALA
SECOND EDITION
Mark C. Lewis
Lisa L. Lacher
CRC Press
Taylor & Francis Group
6000 Broken Sound Parkway NW, Suite 300
Boca Raton, FL 33487-2742
© 2017 by Taylor & Francis Group, LLC
CRC Press is an imprint of Taylor & Francis Group, an Informa business
This book contains information obtained from authentic and highly regarded sources. Reasonable efforts have been
made to publish reliable data and information, but the author and publisher cannot assume responsibility for the valid-
ity of all materials or the consequences of their use. The authors and publishers have attempted to trace the copyright
holders of all material reproduced in this publication and apologize to copyright holders if permission to publish in this
form has not been obtained. If any copyright material has not been acknowledged please write and let us know so we may
rectify in any future reprint.
Except as permitted under U.S. Copyright Law, no part of this book may be reprinted, reproduced, transmitted, or uti-
lized in any form by any electronic, mechanical, or other means, now known or hereafter invented, including photocopy-
ing, microfilming, and recording, or in any information storage or retrieval system, without written permission from the
publishers.
For permission to photocopy or use material electronically from this work, please access www.copyright.com (http://
www.copyright.com/) or contact the Copyright Clearance Center, Inc. (CCC), 222 Rosewood Drive, Danvers, MA 01923,
978-750-8400. CCC is a not-for-profit organization that provides licenses and registration for a variety of users. For
organizations that have been granted a photocopy license by the CCC, a separate system of payment has been arranged.
Trademark Notice: Product or corporate names may be trademarks or registered trademarks, and are used only for
identification and explanation without intent to infringe.
Visit the Taylor & Francis Web site at
http://www.taylorandfrancis.com
and the CRC Press Web site at
http://www.crcpress.com
Contents
Preface xxv
vii
viii Contents
11 Networking 369
11.1 TCP and UDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
11.2 Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
11.2.1 TCP Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
11.2.2 UDP Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
11.2.3 Streams from Sockets . . . . . . . . . . . . . . . . . . . . . . . . . 373
xii Contents
14 Refactoring 449
14.1 Smells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
14.2 Refactorings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
14.2.1 Built-in Refactoring Methods . . . . . . . . . . . . . . . . . . . . . 453
14.2.2 Introduce Null Object . . . . . . . . . . . . . . . . . . . . . . . . . 454
14.2.3 Add and Remove Parameter . . . . . . . . . . . . . . . . . . . . . 454
14.2.4 Cures for Switch Statements . . . . . . . . . . . . . . . . . . . . . 455
14.2.5 Consolidate Conditional Expression . . . . . . . . . . . . . . . . . 456
14.2.6 Convert Procedural Design to Objects . . . . . . . . . . . . . . . . 457
14.2.7 Encapsulate Collection . . . . . . . . . . . . . . . . . . . . . . . . 457
14.2.8 Push Down or Pull Up Field or Method . . . . . . . . . . . . . . . 458
14.2.9 Substitute Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . 458
Contents xiii
15 Recursion 461
15.1 Refresher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461
15.2 Project Integration: A Maze . . . . . . . . . . . . . . . . . . . . . . . . . . 462
15.2.1 The Recursive Approach . . . . . . . . . . . . . . . . . . . . . . . 462
15.2.2 Graphical Editing . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
15.2.3 Longest Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
15.2.4 Optimizing the Maze . . . . . . . . . . . . . . . . . . . . . . . . . 471
15.3 Graph Traversals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
15.4 Divide and Conquer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
15.4.1 Merge Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482
15.4.2 Quicksort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
15.4.3 Formula Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
15.5 End of Chapter Material . . . . . . . . . . . . . . . . . . . . . . . . . . . . 488
15.5.1 Summary of Concepts . . . . . . . . . . . . . . . . . . . . . . . . . 488
15.5.2 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
15.5.3 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490
16 Trees 493
16.1 General Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
16.1.1 Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
16.1.2 Traversals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
16.2 Project Integration: Formula Parsing . . . . . . . . . . . . . . . . . . . . . 498
16.2.1 Formula Tree Traversals and In-Order Traversal . . . . . . . . . . 502
16.3 Binary Search Trees: Binary Trees as Maps . . . . . . . . . . . . . . . . . 503
16.3.1 Order Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
16.3.2 Immutable BSTs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
16.4 End of Chapter Material . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
16.4.1 Summary of Concepts . . . . . . . . . . . . . . . . . . . . . . . . . 514
16.4.2 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
16.4.3 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516
Bibliography 625
Index 627
List of Figures
1 This figure shows the relationships between the chapters in this book to
help you pick which ones you want to cover, and in what order. . . . . . . xxviii
1.1 The Scala API looks like this when viewing scala.collection.immutable.List.
The right column shows the various objects, classes, and traits. Selecting
one shows you the visible members inside of it. This is generated using
ScalaDoc on the library code. . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.1 This is a simple example of a UML use case diagram. Actors are drawn as
stick figures. The system being analyzed is a box. The ways in which the
actors use the system are drawn as circles. . . . . . . . . . . . . . . . . . . 61
2.2 This shows the UML class diagram for the Student class from section 2.2
along with a class for a course that contains multiple students. . . . . . . 62
2.3 This figure shows a use case diagram for a potential bank application that
models the customer-facing aspects of a bank. . . . . . . . . . . . . . . . . 64
2.4 This figure shows a class diagram for a potential bank application that
models the customer-facing aspects of a bank. . . . . . . . . . . . . . . . . 65
4.1 This figure shows a limited set of options for the subtyping relationships of
animals as a UML diagram. . . . . . . . . . . . . . . . . . . . . . . . . . . 118
4.2 This is a simple class diagram showing subtypes of fruit. . . . . . . . . . . 119
4.3 This class diagram for fruit adds some methods that we might want and
how they might be overridden in the subclasses. . . . . . . . . . . . . . . . 120
4.4 Diagram of general subtype relationships in Scala. This figure has been
adapted from a similar figure in Programming in Scala by Odersky, Spoon,
and Venners [10]. The thick lines with full arrowheads indicate a subtyping
relationship. The thin lines with an open arrowhead indicate an implicit
conversion. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
4.5 This UML class diagram shows what is commonly called the diamond prob-
lem. The challenge with this construct is that it can lead to significant
ambiguity. Different languages have different ways of dealing with this. . . 134
5.1 This is a use case diagram for our drawing program. . . . . . . . . . . . . 150
5.2 This is a simple diagram of what we want our GUI to look like when we are
done with the project. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
5.3 This class diagram shows the most of the classes/traits that are relevant
to the ScalaFX scene graph. . . . . . . . . . . . . . . . . . . . . . . . . . . 154
5.4 This is the window that pops up when you run the full version of FirstGUI. 155
xvii
xviii List of Figures
5.5 This is the window that pops up when you run DrawingMain. . . . . . . . 160
5.6 This is a first cut class diagram for our drawing project. . . . . . . . . . . 161
5.7 This is the window that pops up when you run the more complete version
of DrawingMain. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
6.1 This is a UML diagram of the main types in the scala.collection package.
The collection types we have dealt with, including List[A] and Array[A],
have been under the Seq[A] part of the hierarchy. . . . . . . . . . . . . . . 186
6.2 This is a UML diagram of the main types in the scala.collection.immutable
package. This image is significantly simplified. If you look in the API you
will see that most of the types inherit from multiple other types. . . . . . 187
6.3 This is a UML diagram of the main types in the scala.collection.mutable
package. This image is significantly simplified. If you look in the API you
will see that most of the types inherit from multiple other types. . . . . . 188
7.1 This figure shows a graphical representation of the meaning of O. The solid
line represents g(n), which would be a measure of the amount of compu-
tation done for an input size n. The dotted line is the function, c × f (n),
where we want to say that g(n) is O(f (n)). This plot labels a position m,
above which the dotted curve is always above the solid curve. . . . . . . . 216
7.2 This figure shows a graphical representation of an Array-based stack and
how it changes over several operations. The stack stores data in the Array
and uses an integer index to keep track of the position of the top. . . . . . 219
7.3 This figure shows a graphical representation of an Array-based queue and
how it changes over several operations. The queue stores data in the Array
and uses integer indexes to keep track of the front and back. . . . . . . . . 223
7.4 This figure shows a graphical representation of an Array-based queue when
it needs to grow on an enqueue. The queue is seen as empty if front==back.
For that reason, the grow operation should happen when the last slot will
be filled. In addition to allocating a bigger Array, the copy operation needs
to move elements of the Array around and alter the location of front and
back. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
7.5 This is what Eclipse shows when a JUnit test is run and all tests are passed.
A green bar means that everything is good. If you get a red bar, then one
or more tests have failed and they will be listed for you. . . . . . . . . . . 228
7.6 This is the drawing program after adding a maze and executing a breadth-
first solution. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
7.7 This figures shows in a graphical way what happens when a breadth-first
search is run. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
8.1 This figure shows frequencies, transistor counts, and core counts for x86
processors produced between 1978 and 2016. The log scale on the plot makes
it so that exponential curves appear as straight lines. The dotted lines show
fits to the full transistor count data and the frequency data through 2000.
Clock speeds shown are the highest release for each chip. . . . . . . . . . . 245
8.2 This UML diagram shows the main types in the three different parallel
collection packages. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
8.3 This is a screen capture of the drawing program with a Mandelbrot image. 270
8.4 This figure shows a single method call between two objects in a basic se-
quence diagram. The key thing to note is that the thread goes with the call.
So when you call methods, the thread weaves around and between objects. 274
List of Figures xix
8.5 This figure shows three objects and two method calls in a basic sequence
diagram that illustrates how a race condition occurs. Even if the objects
properly encapsulate and protect their values, you still have to use synchro-
nization to prevent race conditions. . . . . . . . . . . . . . . . . . . . . . . 275
8.6 This figure shows three actors and two messages in a basic sequence diagram
that illustrates how the actor model prevents race conditions. Each actor
has only a single thread, and messages are processed sequentially, so as
long as mutable state is confined to a single actor, you cannot have race
conditions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
8.7 This figure shows the organization of the actor hierarchy that we are build-
ing in the example in this section. . . . . . . . . . . . . . . . . . . . . . . . 284
8.8 This is a screen capture of the drawing program with a Julia set image. . 292
11.1 This figure shows the different use cases for the socket/stream-based chat
program that we want to write. . . . . . . . . . . . . . . . . . . . . . . . . 374
11.2 This is a screen shot of the RMI chat client with two users connected. . . 387
11.3 This is a screen shot of the collaboration window. On the left is a column
showing shared drawings. On the bottom is a chat area. The main portion
is a shared sketch region where different collaborators can draw using some
simple types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
12.1 This figure shows what happens when you do an insert and a remove from
an array-based implementation of the list ADT. Note how operations near
the beginning have to do many copies, but operations near the end do not. 407
12.2 This figure shows the basic structure of some different forms of linked lists. 408
12.3 This figure shows what happens with insert and remove on a singly linked
list. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
12.4 This figure shows what happens with insert and remove on a doubly linked
list. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421
13.1 This figure shows how we can do remove from an unsorted array-based
priority queue in O(1) operations after we have done an O(n) search to find
the highest-priority element. . . . . . . . . . . . . . . . . . . . . . . . . . . 435
13.2 This screen shot shows the output of the cell simulation Drawable. The
properties that are used are visible on the left side of the window. . . . . . 439
15.1 This is the drawing program with a sample graph created using DrawGraph. 479
16.1 This figure shows a sample tree with some of the nodes labeled. Node P is
the parent of nodes C, D, and E. D and E are siblings of C. Node P has a
depth of 1 and a height of 2, while node C has a depth of 2 and a height of
1. The size of node P is six, while the size of node C is 2. . . . . . . . . . . 494
16.2 This figure shows the same tree that was displayed in figure 16.1, but draws
arrows for the first-child, next-sibling approach to building the tree. . . . . 495
16.3 This figure shows the same tree that was displayed in figures 16.1 and
16.2. Here, all of the nodes are labeled with letters to aid the discussion of
traversal. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
16.4 This figure shows the recursion that happens when we parse the formula
3*(x-5)+x*x on the left side. On the right is the tree that we would want
to build from this formula. . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
xx List of Figures
16.5 This is an example of a binary search tree using integer value keys. Searching
for an element in the tree follows steps very much like those a binary search
would perform. The bold arrows show the path that would be taken in a
search for the value 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504
16.6 This figure shows the creation of the BST from figure 16.5. Each element
is placed by running down the tree in the same manner as a search until
we hit a location where there is not a child. A new node with the value is
placed in that location. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505
18.1 This figure shows an example of a binary heap. The numbers are priorities
with higher values being higher priority. Note that there is no problem with
duplicate priorities, unlike keys in a BST. There is also no order requirement
between siblings. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540
18.2 This figure shows the same heap as in figure 18.1 with subscripts that num-
ber the nodes in breadth-first order. Below that is an array with the elements
at those locations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
18.3 Adding a new element with a priority of 9 to the heap shown in figure 18.1
goes through the following steps. A bubble is added at the next location in
a complete tree. It moves up until it reaches a point where the new value
can be added without breaking the heap order. . . . . . . . . . . . . . . . 542
18.4 Calling dequeue on the heap at the end of figure 18.3 forces the tree to
go through the following steps. The last element is moved to a temporary
variable, and a stone is placed at the top of the heap. This stone sinks down
until it reaches a point where the temporary can stop without breaking heap
order. The stone always sinks in the direction of the higher-priority child.
If the children have equal priority, it does not matter which side the stone
goes to. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
18.5 This shows a pictorial representation of the alternate data structure that
can be used as an efficient priority queue for collision handling. The top
array keeps the heads of lists for different time brackets during the time
step. The left array is the heads of lists for different particles. All lists are
doubly linked so that nodes can be removed without finding the one before
it. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548
19.1 The binary file holding the linked list has the following format. The be-
ginning of the file is a header with four values written as Longs. They are
the position of the head node, the position of the tail node, the number of
nodes, and the position of the first free node. . . . . . . . . . . . . . . . . 561
19.2 The nodes of a B-tree can each store a certain number of records. The
number of records is selected to match an optimal size for disk reads and
writes. Non-leaf nodes have references to children at the beginning, end,
and between each record. The records in a node are sorted by a key. In
addition, the nodes in children have to have key values that fall between
the keys of the records they are between, or just below and above for the
beginning and end children. B-trees are always balanced and require few
disk accesses to find a record, but they do potentially waste some space. . 565
List of Figures xxi
19.3 This figure illustrates how adds are done for B-trees. A) shows the tree from
figure 19.2 with the addition of a record whose key value is 75. The 75 is
simply placed in sorted order in a leaf because there is still space left in
that node. For B), a record with a key value of 82 has been added. It would
go right after the 75 record, but there is no more space in that node. Of the
five records that would be in the node, the 75 is the median so it is moved
into the parent and the other records are split into two different nodes. This
process can propagate to higher levels in the tree if the parent is also full.
A new level is created when the root node fills and has to split. . . . . . . 566
20.1 This figure shows an example set of points with a very non-uniform spatial
distribution. A regular grid is laid over this to make it clear how the point
density in the grid cells will vary dramatically. The grid size shown here
works well for many of the low-density regions where there are only a handful
of points per cell. A grid that only had a few points per cell in the high-
density regions would be a very fine grid with an extremely large fraction
of the cells being empty in the low-density areas. . . . . . . . . . . . . . . 574
20.2 This is a quadtree with a number of non-uniformly distributed points to
illustrate how the space is partitioned. For this example, each node is only
allowed to hold a single point. The key advantage of the tree-based approach
is that the resolution does not have to be uniform. Higher-density regions
can divide the space much more finely. . . . . . . . . . . . . . . . . . . . . 575
20.3 This is a kD-tree with a number of non-uniformly distributed points to
illustrate how the space is partitioned. For this example, each node can
hold up to three points. While this example only uses two dimensions, it is
simple to scale the kD-tree higher without adding overhead. . . . . . . . . 579
21.1 This figure shows single rotations to the left and the right. These rotations
can be used when a node becomes unbalanced because the outer grandchild
on the left or the right is too tall relative to the other subtree. . . . . . . . 589
21.2 This figure shows double rotations to the left-right and the right-left. These
rotations can be used when a node becomes unbalanced because the inner
grandchild is too tall. Note that each of these is simply two applications of
the rotations from figure 21.1 . . . . . . . . . . . . . . . . . . . . . . . . . 590
21.3 This figure shows two arrays and their possible tree representations. The
second was arrived at by adding the letter ‘t’ at index 5 of the first. In the
tree, each node has the value, a letter, drawn large with a preceding number
that is the size of the node and a following number that is the index. . . . 594
22.1 This figure shows a graphic representation of the idea behind a hash table.
Keys can be any type of data and are not necessarily ordered. The keys are
mapped, using some function that we call the hash function, to positions
in the storage array. There are many more possible keys than there are
locations in the array, so it is possible to have “collisions” where different
keys map to the same location. . . . . . . . . . . . . . . . . . . . . . . . . 610
xxii List of Figures
22.2 This figure illustrates the challenge that we run into when we have the
option to remove a key-value pair when using open addressing. The left
column shows our words and the value given by our hash function using the
division method for an array with 15 elements. The middle column shows
where all those keys would wind up in the table assuming linear probing.
The third column shows it with “a” removed, which would cause problems
if we go looking for “system.” . . . . . . . . . . . . . . . . . . . . . . . . . 618
List of Tables
0.1 This table shows which projects appear as options in each of the different
chapters. The ‘X’ represents a unique project description. An ‘S’ indicates
that there is a standard description for students to use their own implemen-
tation of a data structure in their project. . . . . . . . . . . . . . . . . . . . xxx
3.1 This table shows the precedence rules for operators in Scala. The precedence
is based on the first character in the operator. . . . . . . . . . . . . . . . . . 88
19.1 This table shows how many bytes are written to disk for each of the basic
value types using either DataOutputStream or RandomAccessFile. . . . . . 552
xxiii
Preface
Thank you for purchasing Object-Orientation, Abstraction, and Data Structures Using
Scala. This book is intended to be used as a textbook for a second or third semester
course in Computer Science. The contents of this book are an expanded second edition
of the second half of Introduction to the Art of Programming Using Scala. The first half
of that book became Introduction to Programming and Problem Solving Using Scala. This
book assumes that the reader has previous programming experience, but not necessarily in
Scala. The introductory chapter is intended to quickly bring the reader up to speed on the
Scala syntax. If you already know Scala, you can skim this chapter for a refresher or skip
it completely.
To the Student
The field of Computer Science has remarkable depth. It has to in order to match the
capabilities and flexibility of the machines that we call “computers”. Your first steps into the
field should have shown you how to structure logic and break down problems, then write up
your instructions for how to solve the problems in the formal syntax of some programming
language. In this book, we want to build upon those capabilities. We want to give you
the tools of object orientation to help you structure solutions to larger, more complex
problems without experiencing mental overload in doing so. We also want to expand on
your knowledge of abstraction so that you can make your code more powerful and flexible.
Of course, all of this is implemented using the Scala programming language, which provides
powerful constructs for expressing both object orientation and abstraction.
One of the key ways that we illustrate these concepts is through the creation of data
structures. Data structures form one of the cornerstones of the field of computer science, and
understanding them is essential for anyone who wants to be an effective software developer.1
We strive to show you not only how these data structures can be written, but the strengths
and weaknesses of each one, so that you can understand when you should consider choosing
different ones.
This book also spends a fair bit of time looking at libraries that provide the functionality
you need to do real programming. This includes things like GUIs, multithreading, and
networking. The goal is to put you in a position where you can solve problems that you are
interested in. These are also vitally important topics that grow in importance every day, so
gaining a basic understanding of them early is something that we think is important.
There are a number of resources available to you that help support the mate-
rial in this book. Much of this material is kept at the book’s website, http://www.
programmingusingscala.net/. We teach our own classes using a flipped format, and there
1 One of the authors recently optimized a section of a professional program that was taking 90 seconds
to run down to 0.3 seconds simply by using more appropriate data structures for key operations.
xxv
xxvi Preface
are video playlists for every chapter in this book available at https://www.youtube.com/
channel/UCEvjiWkK2BoIH819T-buioQ. Even if you are not using this book as part of a
course that uses a flipped format, the videos can do something significant that the book
cannot. They can show you the dynamic aspect of programming. Much of the video content
is live coding where we talk through our thought processes as we construct code. This is a
valuable aspect of programming that prose on paper struggles to communicate. Where the
videos are weak is in total depth of coverage. The book goes into much deeper detail on
many topics than what is covered in the videos.
The playlists on the YouTube channel go beyond the contents of this book. They include
the previous book and a number of more advanced topics. We also post more videos on a
regular basis, so feel free to subscribe to see when additional material becomes available.
Lastly, we have put all of the code in this book in a GitHub repository (https:
//github.com/MarkCLewis/OOAbstractDataStructScala) that you can go through and
pull down. The code is organized into separate packages for each chapter. Occasionally
in the text we present changes to earlier code without showing the entire file that re-
sults. Finished files can always be found in the code repository. We have done the same
for the code written in the videos. It is available at https://github.com/MarkCLewis/
OOAbstractDataStructScalaVideos.
We hope you enjoy this step on your journey to learning computer science and developing
your programming skills.
To the Instructor
Why Scala?
Probably the most distinguishing aspect of this book is the choice of Scala as the imple-
mentation language. As an instructor, you inevitably feel multiple influences when selecting
the language to use for introductory courses, especially given that you do not really want to
focus on language at all. You want to focus on concepts, but you know that those concepts
have to be taught in some language so that students can actually get practice. So you re-
ally want a language that will let you teach the concepts that you feel are most important
without getting in the way. Given this, the next obvious question is, why is Scala a good
language for teaching the concepts covered in this book?
There are several pieces to this answer associated with the different groups of concepts
that are covered in this book. First, Scala is an object-oriented language. Much of the
discussion of the language focuses on the functional features of the language, and while
those are wonderful in many ways and the expressivity they bring is used in this book on
many occasions, the reality is that Scala is more object oriented than it is functional. It is
more object oriented than Java, C++, Python, or most of the other languages one might
consider using to teach this material, with the possible exception of Smalltalk and Ruby. All
values in Scala are objects, which simplifies many details compared to languages where there
are distinctions between primitives and objects.2 There is no concept of “static”, which is
replaced by singleton object declarations which fit much better in the OO model. Even the
functions are really just objects with an implementation of the apply method.
2 A favorite example of this is converting between a commonly used type. In Java, why do you say i =
(int)x, but i = Integer.parseInt(s)? Why can you not make an ArrayList<int> but you can make an
int[] which has very different syntax? In Scala you can say x.toInt and s.toInt and you can use the same
Int type with all of your collections which all have uniform syntax.
Preface xxvii
Scala provides many different tools for creating abstraction in code. You have the stan-
dard OO approaches through polymorphism with inheritance and type parameters. You also
have the approaches found in functional languages created by the ease of passing functions
around. Support for pass-by-name adds yet another tool for creating abstraction in code
that is not available in many languages.
Some instructors will also be happy to know that these abstraction tools are all im-
plemented in a statically typed manner. We consider knowledge of type systems to be an
integral part of programming and CS in general. Static type systems have their own formal
logic that can help to structure student thinking and there are certain topics that simply
cannot be taught in dynamically typed languages.
These factors all contribute to the use of Scala for teaching data structures. The language
works very well for teaching students how to construct type-safe collections of their own
from the ground up.
Beyond the keywords in the title of the book, we like to introduce interesting and useful
libraries, which are abundant in both Scala and the broader JVM environment. The ability
to use the advanced multithreading libraries in Scala while also leaning on Java libraries for
things like networking, is remarkably advantageous.
One of the key features of Scala is that it is not opinionated. It lets you do things your
way. Some people lament that in professional environments. However, in the classroom, that
means that you can teach what and how you want. You can use declarative constructs if
you want to focus on higher level thinking or use imperative constructs when you want your
students to have to deal with the details. A general idea behind Scala is that there is no
silver bullet for most problems in computer science, so a language should provide you with
options to do things in the way that you feel is best. We believe that this matters as much
in the classroom as in other venues.
Lastly, there are the influences beyond pedagogy. There are considerations of how a
language fits into the full departmental curriculum and how it impacts students outside
of your curriculum. Scala works well beyond just the introductory courses. It is broadly
used in web development, has a significant range of tools for parallelism, and thanks to the
Spark library, it has become a dominant force in the area of data analytics. As a result,
it is not hard to envision Scala being used in later courses in the curriculum. As for real-
world usage, we would argue that Scala sits in the sweet spot for pedagogy. It is being
broadly used outside of academia. At the time of this writing, it was number 14 on the
latest RedMonk language ranking, sitting at roughly equal position on both the GitHub
and StackOverflow axes of that ranking. This is high enough that you can point students,
parents, and colleagues to real-world usage. However, it is far enough down that students
are less likely to be able to find answers to all of your programming assignments with a
simple Google search.
While there is no perfect language for anything, we do believe that for these reasons,
and likely others that we have missed, Scala is a good option for introductory programming
courses.
FIGURE 1: This figure shows the relationships between the chapters in this book to help
you pick which ones you want to cover, and in what order.
Preface xxix
There are also a few additional topics thrown in that we feel can go well in a CS2
course. These include GUIs, basic graphics, multithreading, and networking. We picked
these because they allow students to write more “real” programs that they will hopefully
find interesting. Also, in the case of multithreading and networking, these topics grow in
importance every day, and having some exposure to them early is something we feel benefits
students.
This book does assume that students have had at least one semester of previous pro-
gramming instruction. If your students are coming to this book without having used Scala
previously, the first chapter is intended to be a quick introduction to the key points of the
language. We provide an appendix with a basic refresher on recursion for those students
who did not cover that previously. We do not include basic sorting and searching. If your
students have not previously seen that, you will want to cover it in some form at or before
chapter 4.
There is a lot of material in this book. It is not expected that any course will cover all of
it in one semester. If your students used Introduction to Programming and Problem Solving
Using Scala in a previous semester, then chapters 1 and 5 can be easily skipped. Even with
that, there is still more than most instructors would wish to cover in a semester. This is
intentional, as we expect that you will focus on different material based on whether you are
using this for a 2nd or 3rd semester course. Figure 1 shows a basic representation of the
chapter dependencies in this book. A line between chapters implies that the later chapter
uses material covered in the earlier one. As you can see, there are a number of chapters off to
the side that can be skipped or covered in a different order without running into problems.
As mentioned in the section addressed to the student reader, there are a number of online
resources associated with this book. The online videos were created by us for use in our own
flipped classroom setting. If you use a blended approach in any way, we strongly encourage
you to make use of these videos. Producing videos takes roughly as long as writing a book,
and they allow students to see live coding, which we consider to be extremely valuable.
There is also a GitHub repository with all of the code that we wrote for this book. We
hope that you find these, and other resources on the course website, to be of value in your
teaching.
Projects
One of the key issues with teaching object orientation is that the strengths of the OO
approach really come out when programs get longer. In order to highlight this with students,
you have to have them see and work on larger pieces of code. Beginning in chapter 5, we
create a project that is utilized in most of the later chapters in the book to illustrate how to
use the concepts that are discussed in an application that is a few thousand lines in length.
We also provide both exercises and projects at the end of each chapter. The exercises
are intended to be simple, one-off tasks that students can use to test their knowledge of
the contents of that chapter. The projects are continued across multiple chapters to give
students a chance to build their own larger applications. Table 0.1 shows which chapters
the projects appear in so that you can determine which ones are best suited to the material
that you intend to cover from this book.
The table uses short names for the projects. Here are brief descriptions as well. Long
descriptions can be found in the projects section of chapter 3.
• MUD - This is a multi-player text-based game. It works particularly well for high-
lighting the actor style of parallelism, but can be done without that.
• Spider - This is a web spider/crawler that follows links on web pages to collect infor-
mation from a site.
xxx Preface
Chapter MUD Spider Game Math Image Sim Stocks Movies L-Systems
1. Scala Basics
2. OO Basics
3. OO Details X X X X X X X X X
4. Polymorphism X X X
5. GUIs X X X X X X X X X
6. Collections X X X X X X X X X
7. Stacks & Queues X X X X X X X X X
8. Multithreading X X X X X X X X
9. Low-Level Threads X X
10. Streams X X X X X X X X X
11. Networking X X X X X X X X
12. Linked Lists S S S S S S S S S
13. Priority Queues X X X X X X X
14. Refactor
15. Recursion X X X X X X X X X
16. Trees X X X X X X X X X
17. Regex/Parsers X X X X X X X X X
18. BinaryHeaps S S S S S S S
19. Binary Files X X X X X X
20. Spatial Trees X X X X X X X
21. Augmented Trees X X X X X X X
22. Hash Tables S S S S S S S S S
TABLE 0.1: This table shows which projects appear as options in each of the different
chapters. The ‘X’ represents a unique project description. An ‘S’ indicates that there is a
standard description for students to use their own implementation of a data structure in
their project.
• Game - This option has students create a graphical game. There are technically two
paths to this, one for a standalone game and one for a networked game.
• Math - This is short for “Mathematics Workbench”. It has students write something
like a baby Mathematica R worksheet program.
• Sim - This is short for “Simulation Workbench” in which students write a variety of
types of simulations and integrate them into a single, larger project. The simulations
include N-body physics simulations as well as discrete event simulations.
• Stocks - This is a networked, stock portfolio management system that involves pulling
stock data from the web and helps users manage their stock portfolio.
• Movies - This project involves keeping an inventory of movies with the eventual goal
of setting up a little business that rents/streams movies to users. Users can track
rental requests, favorites, and movies already rented.
• L-Systems - In this project, students play with the formal grammars known as L-
systems that can have interesting turtle graphic interpretations that produce fractals
and structures that resemble biological forms.
Chapter 1
Scala Language Basics
This book assumes that you have previous programming experience, though perhaps not
with Scala. This chapter is intended to get you up to speed on the basic syntax and semantics
of the Scala language. If you have previous experience with Scala, this can be a refresher.
If your previous experience is in some other language, this chapter will help introduce you
to the key concepts that you need to use in later chapters.
Programming languages are generally classified by different paradigms. A paradigm
is an approach that a language takes to organizing code and solving problems. The four
main paradigms of programming are imperative, functional, object-oriented, and
logic. Scala is generally described as both functional and object-oriented, but it is not
strictly functional, as it allows the imperative style as well. This combining of paradigms
is becoming more common, and even older languages, like Java and Python, have gained
features that also allow them to use aspects of all three of these paradigms. In Scala, one
1
2 Object-Orientation, Abstraction, and Data Structures Using Scala
often prefers more functional approaches, while languages like Java and Python are naturally
imperative with functional features.
Through the course of this book, and hopefully later in your education, the meanings of
these terms and the features of the various paradigms will become clearer. The discussion
in this book will generally explicitly say whether code is written in a way that is more
functional or more imperative, and everything in Scala is fundamentally object-oriented.
Depending on your background, different things here might look unfamiliar, so we will
go through the elements one at a time and compare them to what you might have seen
previously. For comparison, and to aid the following discussion, here are similar programs
written in Java and Python.
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello world!")
}
}
def main():
print("Hello world!")
main()
This Python code is more complex than is really required. The definition of a function is
included to make it more similar to the others for comparison purposes.
The main code of the Scala application is inside of an object declaration. We will discuss
the meaning of the object declaration more in chapter 3 where we will also contrast it to
the more commonly seen class declaration. For now, we will just say that this creates
what is called a singleton object. An object is something that combines both data and
1 http://www.programmingusingscala.net
Scala Language Basics 3
functionality. This declaration begins with the keyword object followed by the name we
want to give our singleton object, then there is a block of code enclosed in curly braces. It
is customary to use the camel case naming scheme in Scala, where each word begins with
a capital letter. The names for objects also start with a capital letter.
All declarations in Scala begin with a keyword. The object keyword declares singleton
objects. The only thing we have put inside the body of our object is a method called main.
Methods are declared with the def keyword. That is followed by the name of the method,
then the parameter list with types in parentheses, the result type after a colon, then an
equal sign and the body of the method. The names of methods should also use camel case
naming, but they should begin with a lowercase letter.
The body of the main method is identified by curly braces. Inside is a single line that
calls the println method and passes it the String that we want to print.
If you are coming to Scala from Java, a lot of this will look familiar. You are used to
seeing class instead of object, and while you would not use def, you would have public
static on your main method. In Java, you put the types before the things they modify, like
the method result and the type of the argument, args. In Scala, types come after things
such as methods, variables, etc., when they are specified, and they are separated by a colon.
If you see a colon in Scala, the thing to the right of it will be a type that is attached to
the thing to the left of it. You also notice that the type is Array[String] in Scala instead
of the String[] that is used in Java. Unlike Java, there is also no semicolon at the end of
the line calling println. Like Java, Scala does use semicolons to separate statements, the
difference is that Scala will infer semicolons at the end of lines where they make sense so
that you do not have to type them. You can still put semicolons at the end of lines, or use
them to separate multiple statements on a single line, but such style is typically frowned
on in Scala.
If you are coming from a Python background, there are good odds that you have just
been writing functions with def and not putting them inside of classes. In Python, there
are no curly braces, and indentation is meaningful to the program. In Scala, it is the curly
braces that are meaningful and indentation, which you really should continue to use, is for
the purposes of human readability.
Unlike Java, Python is a scripting language, and so simple programs like this one are
often just written as executable lines of code with no declarations at all.2 There are good
odds that your introductory course using Python showed you how to declare functions using
def, but it likely did not show you class declarations, or other aspects of object-oriented
programming. Also, while there is some meaning to the concept of “main” in Python, it is
only by convention that programmers write a main function. The language does not require
it. When writing a Scala application, there has to be a main method that takes a single
argument of type Array[String] that is declared inside of an object.3
The biggest difference between Python and Scala is the fact that types are specified
at all. Python is a dynamically typed language. The system it uses for checking types is
commonly called “duck typing”.4 Languages that use duck typing check that values have
the right operations at runtime. If they do not, an error is produced. Scala, on the other
hand, is a statically typed language. This means that, in general, all types are checked
2 Scala scripts are the same way. Writing “Hello World” as a Scala script requires just the single line
println("Hello world!"). The additional lines are provided here because we are focusing on applications,
not scripts.
3 In chapter 4 we will see that you can write applications in a manner where you do not explicitly create
duck. So if a value supports the operations that are needed by a piece of code, then clearly it was of the
right type.
4 Object-Orientation, Abstraction, and Data Structures Using Scala
for correctness by the compiler before the program is run. In this chapter, you will see
that in many places, Scala will figure out types for you. However, there are some places,
like the parameters to functions, where they have to be specified by the programmer. This
might seem tedious, but it allows the compiler to catch a lot of errors earlier, which is very
beneficial for large code bases or projects that are being worked on by many people.5
1.2 Comments
Comments are an essential part of any real-world programming project. Good code is
written in a way so that other people can read it. There are many things that you can do to
help make code readable, including using names that are meaningful. Still, there are times
when you really need to explain what is going on in plain English or to provide additional
information related to the code. This is where comments come in.
Scala style comments are just like Java style comments. You can make a single line
comment with //. Anything that you put after the // on that line will be part of a comment.
Multiline comments begin with a /* and end with a */.6 These comments can include almost
any text you want, including newlines. Just note that a */ ends the comment.
Scala also has an automatic documentation generating tool called ScalaDoc that builds
web-based documentation from code. This tool looks for multiline comments that start with
/**. The extra * does not matter to the compiler, as the /* starts a comment, but it tells
the documentation generator that the comment holds information that is intended to go in
the documentation. For an example of the type of page generated by ScalaDoc, see figure 1.1
later in this chapter, which shows the official Scala library documentation that is generated
with ScalaDoc.
The following code shows what our first application might look like if we added some
comments.
/** Our first application. */
object HelloWorld {
/** The entry method that is run for this application.
*
* @param main the arguments from the command line
*/
def main(args:Array[String]):Unit = {
println("Hello world!") // This call to println sends text to standard output.
}
}
ScalaDoc comments go directly before the declarations that they provide information for.
You can see from the comment on main, that there are some special elements that begin
with @ that provide additional information. In addition to @param, you will see the use of
@return and @constructor later in the book. ScalaDoc is heavily modeled off of JavaDoc,
so if you have experience with using JavaDoc comments, the same attributes will generally
work with ScalaDoc as well.
The comment on println in this example would generally be considered superfluous.
5 One could argue that the lack of compile time type and syntax checking is a big part of the reason why
large projects written for Python 2 have been slow to migrate to Python 3.
6 Note that multiline comments do not have to span multiple lines. They can begin and end on the same
line.
Scala Language Basics 5
Here again, there are differences between Scala and other languages you might have learned.
In Python, you do not declare variables, you simply assign values to names and start using
them. This difference exists in part because Python is dynamically typed, so the names do
not have types associated with them. A name can hold a numeric value on one line, then
be assigned a string value on the next, and a list value on a third. Doing so is probably a
bad idea that leads to code that is hard to work with, but Python does nothing to prevent
you from doing it.
If your background is in Java, you are used to declaring variables, but you are used to
putting types in the place where Scala puts val or var. You probably immediately noticed
that this code does not specify types. That is because Scala does local type inference. That
means that Scala will try to figure out the type of things based on information on the
current line. As long as it can, you do not have to specify the type yourself. You can if you
wish though. The previous two lines could have been written, using explicit types, in the
following way.
val name:String = "Pat Smith"
var age:Int = 18
Consistent with what we saw for functions previously, the types are given after the variable
names and separated from the names by a colon. Note that both types start with a capital
letter. In Java, primitive types begin with lowercase letters and object types begin with
capital letters. In Scala, there are no primitive types, and all types begin with capital
letters.7
7 In Scala, the types that were primitives in Java are generally called value types, and the types that
came from Object are called reference types. The distinction between these is discussed more in chapter 4.
6 Object-Orientation, Abstraction, and Data Structures Using Scala
Another difference between Scala and Java is that variable declarations in Scala have to
be given an initial value.8 Inside of methods you cannot have declarations like these where
you would give them values later.
val name:String
var age:Int
This makes the language safer, as uninitialized variables are common sources of errors in
languages that allow uninitialized variables.
An obvious question at this point is, what is the difference between a val declaration
and a var declaration. The answer is that you can change what value is referenced by a
var declaration, but you cannot for a val declaration. In Java terms, the val declaration
is final, and the var declaration is not. So you cannot do later assignments to a val
declaration.
name = "Jane Doe" // This is an error: cannot assign to a val
age = 19 // This compiles just fine
A general rule of thumb in Scala is that you should use val declarations as much as possible,
and only go to var declarations when needed. This is part of the functional paradigm. Odds
are good that your previous exposure to programming has largely used the imperative
paradigm. In this paradigm, re-assignment to variables is common. The values of variables
are called the state of the program, and assignment changes state. The functional paradigm
typically avoids changing or mutating the state. This actually makes it easier to think about
the logic of the program when the value of a variable, once created, does not change.
One last thing to note deals with variable naming conventions. In Scala, variable names
should start with lowercase letters, just like method names. If the name was made up with
multiple words, it would use camel case with the first word in the variable name starting
with a lower case letter and each subsequent word capitalized. The names were also picked
to have meaning. Hopefully this is something that you learned previously: that you should
choose meaningful variable names. Using names that are not meaningful makes programs
much harder to work with, especially for programs that are used over a long period of time
and have multiple programmers editing them.
You can get started in Scala with only a few different types. The following list gives the
basics in alphabetical order.
• Boolean - This type is used for decision logic. It has only two values, true and false,
that can be used as literals in your programs.
• Char - This type is used to represent single character values. You can make literal
characters by putting the character you want in single quotes. For example, ‘a’ or
‘0’.
• Double - This type represents general numbers that might not be integers. They are
stored using the IEEE double precision floating point standard. It is worth noting
that these are not equivalent to the real numbers from mathematics, which have
infinite precision. Numbers that include decimal points, like 3.14, or that use scientific
notation, like 1e100, have this type.
• Int - This type is used to represent integer values. They are stored as 32-bit, signed
binary numbers. If you enter a number that does not have a decimal point or scientific
notation, it will have this type.
8 In chapter 4, we will see that members of classes and traits can be declared without giving them
values, but in Scala that means they are abstract, so the semantics are different from Java.
Scala Language Basics 7
• String - This type is used for representing sequences of characters used for text. You
can create a String literal in your program by putting text between double quotes,
like "Hello".
• Tuples - These are ordered groups of types. You can make them in your code by
putting comma-separated values inside of parentheses. So (1, 3.14, "Hello") is a
tuple with the type (Int, Double, String).
• Unit - This is a type that represents a value that carries no information. There is only
one instance of Unit, and it is written as (). You can get the values out of a tuple
with methods called 1, 2, etc. or using patterns, which will be discussed later.
The fact that every value in Scala is an object means that you can call methods on all
values, regardless of their type. To convert between types, there are methods like toInt or
toString that implement meaningful conversions. So if you had a variable called num with
the value "42", you could use num.toInt to get the value as an integer. For the numeric
types, you can also call MinValue and MaxValue to get the range of allowed values.
This is by no means a complete list of types. Such a list cannot be made, as there are
effectively an infinite number of types. A lot of this book will focus on how we create our
own types in Scala. This is just the minimum set needed to get you up and running in Scala.
We will see more later on.
There are a few other details of the Char and String types that need to be considered
here as well. The normal Char and String literals cannot include line feeds, and there are
challenges dealing with some other characters as well. For that reason, there are escape
characters that likely mirror those that you have seen previously involving a backslash and
various characters. Scala also support raw strings, which are String literals that can
span multiple lines and do not treat the backslash as an escape character. The raw strings
in Scala begin and end with three double quotes. You can put anything inside of them
except for a sequence of three double quotes.
Strings in Scala support concatenation using the plus sign. So you if have the variables
name and age defined above, you can do something like this.
val message = name + " is " + age + "."
This will build a longer String and give it the name message. This syntax is rather long,
and can get unwieldy if you need to append many variables into a formatted String. For
that reason, Scala also supports string interpolation. To make an interpolated String,
simply put the letter s in front of the double quotes. That allows you to insert variables
with a dollar sign. The previous declaration could be written in the following way using an
interpolated String.
val message = s"$name is $age."
If you need a more complex expression in the interpolation, you can put it in curly braces
after the dollar sign. For example, if you wanted to do arithmetic on a value and interpolate
the result you could do something like this.
s"$age times two is ${2*age}."
The curly braces are required after the second dollar sign.9
9 There is another form of interpolation where you prefix the double quote with an f and then use C-style
formatting in the String. We will not use that type of string interpolation in this book.
8 Object-Orientation, Abstraction, and Data Structures Using Scala
This is especially handy when you need to repeat a string a variable number of times, often
to produce some type of formatting. This is also something that Python users will find
familiar.
However, there are a few more differences between Scala and Python. First off, in Scala
there is no ** operator provided for doing exponentiation. You can do exponentiation with
the math.pow(x:Double, y:Double):Double method from the library. Similarly, there is
no // operator to do floor division. If you divide two Ints, the result will be a truncated
Int. If you divide two Doubles or a Double and an Int, the result will be a Double that is
as close as possible to the result of that division. The following four expressions illustrate
this.
Scala Language Basics 9
If you do an operation between two arguments of different types, the less general type is
elevated to the more general type, and the operation is done between those values.
There are also differences between Scala and Python in the area of logical operators.
While Python uses and, or, and not, as the logical operators for Boolean values, Scala
uses the C-style operators of &&, ||, and ! respectively. The && and || are short circuit
operators, so if the value can be determined by the first argument, the second argument is
not evaluated. If you happened to learn Python 2.x, you might also have seen <> used to
represent not equal. Scala, like Python 3.x, will only accept != for not equal.
We declare square to be the name of the function created by our lambda expression.
Note that you call the lambda expression just like you would a function, by putting the
argument(s) in parentheses after the name. The syntax shown here specifies the type of the
argument for the lambda expression, and Scala figures out the result type. As a general
rule, we do not have to specify things that Scala can figure out, and most of the time, we
will leave that off. Most uses of lambda expressions are in situations where the type of the
lambda expression is completely known.
We can define the same function using a different approach where we put the type on
the name and the lambda expression itself does not have any types.
val square:(Double)=>Double = x => x*x
Here we explicitly give the type of the lambda expression. These types include a rocket,
just as the lambda expressions do. So (Double)=>Double means a function that takes a
Double, represented by the type in parentheses to the left of the rocket, and produces a
Double, shown by the type to the right of the rocket. The parentheses could include multiple
types separated by commas if the function has multiple parameters. They can also be left
off completely if there is only a single parameter. So in this case, the type could have
been written as Double=>Double. Because the type has been specified early, the lambda
expression does not require a type specification on the parameter. This is more similar to
what you will do most of the time when you write lambda expressions.
10 Object-Orientation, Abstraction, and Data Structures Using Scala
There is also a shorter syntax that works for creating lambda expressions that works
for simple expressions where any parameters appear only once each and in order. In these
situations, you can use underscores as place holders for the parameters, and you do not use
the rocket at all. The square function does not fit that rule because the parameter x is used
two times. Instead, we can make a function called twice that simply doubles the value of
the input. Here it is defined using the rocket syntax.
val twice:Double=>Double = x => x*2
The rules for exactly when you can use the underscore syntax are somewhat complex. A
practical approach is that if you are using the underscore syntax and you get odd error
messages, you should switch to the rocket syntax.
One last thing to note about lambda expressions is that they should typically be short.
The ones shown here have a single, simple expression as the body of the lambda. This is the
ideal usage. You can use curly braces to make more complex expressions, but if your lambda
expression is more than a few lines long, it probably should not be written as a lambda
expression. You should likely pull it out and make a full method with an informative name
instead. These can be passed into places that call for functions just as easily as lambda
expressions can.
1.5.1 Conditionals
The most basic control structures are conditionals. Every language needs some way of
saying “if”. In most languages, that is exactly how you say it. Scala is not an exception.
The syntax for an if looks like if(conditional ) trueCode else falseCode. The conditional
can be any expression with a Boolean type. The trueCode is what will be evaluated if the
condition is true and the falseCode is what will be evaluated if the condition is false. The
else and the falseCode are both optional, but you will probably include them in Scala
more than you might in other languages. If trueCode or falseCode need to include multiple
statements, curly braces are used to form a block of code.
That description probably sounds very much like what you have seen previously. Where
the if in Scala differs from that seen in most non-functional languages is that it can be
used as either a statement or as an expression. In both Java and Python, the if is only
a statement. It is not an expression because it does not evaluate to a value. In Java and
Python, when you need to make a conditional expression, you do so with the ternary
operator, ?:. Scala has no need for the ternary operator because if works just fine as an
expression.
Scala Language Basics 11
To make this clear, consider the simple example of determining the price of a ticket at
a movie theater. Assume we have a variable called age and that the price of a ticket is $8
for kids under 12 and seniors over 65, and $12 for everyone else. We can write this in an
imperative way using a var declaration and the if as a statement as follows.
var price = 12
if (age < 12 || age > 65) {
price = 8
}
While this is perfectly valid Scala code, this is not how you would normally write this in
Scala. As was mentioned earlier, we would prefer to use a val declaration when possible. In
this situation, that is easy to do if you use the if as an expression instead of a statement.
In that situation, the same code looks like the following.
val price = if (age < 12 || age > 65) 8 else 12
Here the if produces a value, and that value is given the name price. Doing it this way
means that we cannot accidentally mess up the value of price later by doing some other
assignment to it.
It is worth noting that when you use the if as an expression, you almost always want
the blocks of code for the true and false conditions to have the same result type. It really
does not make much sense for the true option to produce an Int and the false option to
produce a String. Such a line of code might be valid Scala code that compiles, but the
value that you get from it will have an unusual type that you cannot do much with.10
Scala allows you to nest any language construct inside of any other language construct.
One implication of this is that you can put an if inside of another if. There is no special
syntax for doing this. Normally, when you nest things, the nested code should be indented
inside of curly braces. One common exception to this rule is when you have if statements
or expressions nested in the else part of another if. In that situation, it is commonly
accepted to format your code in the following way.
if (cond1) {
...
} else if (cond2) {
...
} else if (cond3) {
...
} else {
...
}
For those coming from Python, you should know that there is no pass statement in Scala.
It would be rather unusual to include a condition that you do not want to do anything for
in Scala, but if you do, you can leave the curly braces empty. Note that doing so only really
makes sense when you are using the if as a statement and not an expression. If you use it
as an expression, that means that you are expecting it to result in a value, and the empty
code will produce the type Unit, which generally will not be helpful.
Scala includes a second conditional statement called match. This is a multiway condi-
tional that is decided on a single value. For those with a Java background, it might sound
like a switch statement, but it is a far more powerful construct than the switch. The
general syntax for match is as follows.
10 The details of the type that is produced will be discussed in chapter 4.
12 Object-Orientation, Abstraction, and Data Structures Using Scala
expr match {
case pattern1 => expr1
case pattern2 if cond => expr2
...
}
Each case has a pattern and an optional if guard. An if guard can be used to fil-
ter the results even further. Patterns play a role in a number of different constructs in
Scala. They can be as simple as a value or a name, but they can be more complex. For
example, you can make patterns that match tuples. The following example shows a match
that could be used as part of the classic “Fizzbuzz” problem. In this problem, you are sup-
posed to print all the numbers from 1 to 100 except that you substitute “fizz” for values
that are divisible by 3, “buzz” for values that are divisible by 5, and “fizzbuzz” for values
are that divisible by both. This code assumes that the value in question has the name i.
(i % 3, i % 5) match {
case (0, 0) => "fizzbuzz"
case (0, _) => "fizz"
case (_, 0) => "buzz"
case _ => i.toString
}
The way a match is evaluated is that we go from the first case down, and use the first one
that matches. There are several things to note in this example. The underscore is used as a
wildcard. It matches anything, without giving it a name. You could replace the underscores
with variable names, and the values of that part of the expression would be bound to that
name. You would do that if you wanted to use that value in the expression for that case.
Order clearly matters as the last case matches everything.
Like the if, the match in Scala is an expression. It produces a value given by the
evaluation of the expression for that case. This is being used in the Fizzbuzz example
above. Note that the code does not print or change anything, it simply produces different
values based on the value of i. As with the if, this is generally only meaningful if every
case results in the same type.
The expression in each case can be arbitrary code, and it can span multiple lines. You
do not need curly braces for this, as Scala knows that the current case ends when it sees
the next occurrence of the case keyword. If you are used to the switch statement in Java,
you know that it requires the user to put break statements at the end of cases to prevent
the execution from falling through. That is not the case with match in Scala. Indeed, there
is no break in Scala, and control only goes to one case on an execution of a match. It is
also worth noting that your cases need to cover all possibilities. An error will occur if you
execute a match and none of the cases actually match the expression.
1.5.2 Loops
Another class of language constructs are loops, which give you the ability to have code
execute multiple times. The most general loop is the while loop, which exists in both Java
and Python. The syntax in Scala is identical to that in Java. It looks like the following.
The body of the loop is generally longer, so most of the time you will see it put in curly
Scala Language Basics 13
braces though they are not technically required if there is only a single statement. The
while loop is a pre-check loop that checks if the condition is true before executing the
body. Scala, like Java, but unlike Python, also includes a post-check do-while loop. The
syntax of this loop is as follows.
do body while(condition)
The only difference between the two is that the body of the do-while loop will always
happen at least once, because the condition is not checked until after it has happened. The
body of the while loop might not happen at all. Both the while and do-while loops should
only be used as statements. If you use them as an expression, the result is always of type
Unit.
The more interesting loop in Scala, and most other languages, is the for loop. In its
simplest usage, the for loop in Scala is like the for-each loop in Java or the for loop in
Python. That is to say that it runs through the elements of a collection. A basic usage of
the for loop in Scala might look like the following.
for (i <- 1 to 10) {
println(i)
}
Looking at this code, it should be pretty clear that it will print the numbers 1 to 10 on
separate lines. A more general view of this basic syntax is as follows.
The pattern can be as simple as a variable name, as seen in the example above, or some-
thing more complex, like tuples. If the pattern does not match an element of the collection,
it is simply skipped over, and no error occurs. We will see more about the collections in
section 1.7.2. The 1 to 10 from the example above produces a type called a Range and it
is actually calling the method to on the Int 1, and passing it an argument of 10. There
is also an until method that makes the upper bound exclusive. The arrow between the
pattern and the collection is often read as “in”. The combination of pattern <- collection
is called a generator.
The for in Scala can do a lot more than just this simple iteration through a single
collection. The example above uses the for loop as a statement that does things, but does
not produce a value. By including the yield keyword before the body, we can turn the for
into an expression.
This expression will produce a new collection with the values that the body evaluates to on
each time through the loop. So the following will declare squares to be a collection with the
values 1, 4, 9, ..., 100.
val squares = for (i <- 1 to 10) yield i*i
You can also specify multiple generators in a for loop that are separated by semicolons.
You can also specify if guards and variable declarations. These are also separated by
semicolons. Instead of using semicolons, you can replace the parentheses with curly braces,
and put newlines between each of the different elements in the for. The following example
illustrates multiple generators, a variable definition, and an if guard to create a variable
14 Object-Orientation, Abstraction, and Data Structures Using Scala
called evenProducts that contains the even elements from the products of the numbers
between 1 and 10.
val evenProducts = for (i <- 1 to 10; j <- 1 to 10; product = i*j;
if product % 2 == 0) yield product
This formatting with multiple things on the same line is often challenging to read. You can
put newlines after the semicolons, but Scala also allows for loops that use curly braces in
place of the parentheses. When this syntax is used, semicolons are put on new lines, just
like for normal Scala code. Using this, the previous for loop looks like the following.
val evenProducts = for {
i <- 1 to 10
j <- 1 to 10
product = i*j
if product % 2 == 0
} yield product
This style of formatting with the curly braces using multiple lines is considered proper Scala
style when there are multiple generators, if guards, or variable declarations.
It was mentioned in section 1.5.1 that there is no break in Scala. This also applies to
loops. It simply is not a keyword in the language. Similarly, the continue statement that
you might have used in loops in Java or Python does not exist in Scala.
try
expression
catch {
case pattern =>expression
case pattern =>expression
...
}
finally expression
The catch or the finally can be left off. The cases in the catch should have an ap-
propriate pattern for the type of error they are set up to handle. The following example
assumes we have a variable called str that holds a String that we would like to convert
to an Int using toInt. If the value of str is not a valid integer value, this will throw a
NumberFormatException. The one case uses a pattern that matches on the type so that
if this happens, a value of 0 is produced. The e that you see in this code is just a variable
name, that will contain a reference to an object of type NumberformatException if str is
not a valid integer value.
val num = try {
str.toInt
} catch {
case e:NumberFormatException => 0
Exploring the Variety of Random
Documents with Different Content
Daughter of faith, awake, arise, illume
The dread unknown, the chaos of the tomb;
Melt and dispel, ye spectre-doubts, that roll
Cimmerian darkness on the parting soul!
Fly, like the moon-eyed herald of dismay,
Chased on his night-steed by the star of day!
The strife is o’er—the pangs of nature close,
And life’s last rapture triumph’s o’er her woes.
Hark! as the spirit eyes, with eagle gaze,
The noon of heaven undazzled by the blaze,
On heavenly winds, that waft her to the sky,
Float the sweet tones of star-born melody;
Wild as that hallow’d anthem sent to hail
Bethlehem’s shepherds in the lonely vale,
When Jordan hush’d his waves, and midnight still
Watched on the holy towers of Zion hill!
Soul of the just! companion of the dead!
Where is thy home, and whither art thou fled?
Back to its heavenly source thy being goes,
Swift as the comet wheels to whence he rose;
Doom’d on his airy path awhile to burn,
And doom’d, like thee, to travel and return.
Campbell.
A Heaven as bright, as blue, as mild, as calm,
As thine own eye; the sun hath passed away,
But left his mantle of transparent light
To deck the gorgeous west, amid whose bright
And purple depths I see a floating speck
Of purest white, and now ’tis fixed, and now
Swells into clearest beauty—’tis a star,
Whose trembling orb seems shrinking from the light,
Like a rebuked seraph’s eye, when drooped
’Neath the chastising glance; a bright ray shoots
Up from its centre; gradual the star
Severs before that ray, it parts—it spreads—
And from its heart comes forth a gliding form,
Surpassing all my mortal thought of beauty:—
* * * * *
* * * * *
Celestial voices
Hymn it unto our souls.
R. H. Dana.
HYPOCRISY.
The hypocrite’s hope shall perish.—Job, viii. 13.
The triumphing of the wicked is short, and the joy of the hypocrite but for a
moment.—Job, xx. 5.
For the vile person will speak villany, and his heart will work iniquity, to practise
hypocrisy, and to utter error against the Lord.—Isaiah, xxxii. 6.
When thou doest thine alms, do not sound a trumpet before thee as the
hypocrites do in the synagogues and in the streets, that they may have glory of
men.
When thou prayest, thou shalt not be as the hypocrites are; for they love to
pray standing in the synagogues and in the corners of the streets, that they may
be seen of men. Verily I say unto you, They have their reward.—Matthew, vi. 2, 5.