Scala Materials Scrubbed
Scala Materials Scrubbed
Null pointers are the source of a lot of evil stuff in computer programming, in lesser languages we're
often forced to write code littered with IF conditions to make sure that we don't end up invoking
methods on a null reference somewhere far away from where the null first snuck into the system.
Benefits of not using null are:
Null does not exist in idiomatic Scala; if not for Scala's deep Java interoperability we might be able to
forget it exists at all. If a Scala library—third-party or internal—consider it buggy and file an issue.
When you need to write Scala code interacting with Java APIs, wrap potential null cases to prevent
them leaking out to the rest of your program.
These articles are helpful to reinforce the Why and How about not using null:
Internal
// DO NOT
val buf = ListBuffer.empty[String]
for (word <- words) {
buf += word.toUpperCase
}
val upcased = buf.result
// DO
val upcased = words.map(word => word.toUpperCase)
Not only less code, but also more declarative rather than imperative—emphasis is on what is being
done instead of how a loop works.
In Scala the common case is transforming an immutable collection, not updating a mutable one. This
ensures thread safety and paves the way to parallel operations (maybe you've heard of
map/reduce…).
3. Case classes should be used as data containers and only as data containers
6. Avoid explicit casting and type checking, use pattern matching instead
7. Companion objects should be used if they are beneficial to the class they are companioned
with
The Scala object keyword defines singleton objects. These are good for static data and methods,
like constants and pure utility functions. Don't use them for state—using objects for mutable state
will lead to the bad, troublesome design patterns characteristic of globals, to concurrency
synchronization bugs, and to code that is difficult if not impossible to unit test properly.
Internal
Testing in Scala
The book Testing in Scala, although now dated, still covers in detail the essentials of the main test
frameworks in the Scala ecosystem: ScalaTest, specs2, and ScalaCheck. All are used in Agoda in
different projects—find out what your team uses and focus on reading about it.
Mocking
Most projects in Agoda use either ScalaMock or Mockito for mocking. Again, learn what your team
uses and:
• Read Chapter 5
If you're starting new projects, ScalaMock is recommended because it supports language features of
Scala that Mockito (a Java framework) cannot handle well.
Configuration in Scala
Read the README for https://github.com/lightbend/config up until (not including) "Miscellaneous
Notes".
Lightbend/Typesafe Config is widely used throughout the Scala ecosystem—it's likely to be used by
libraries and frameworks you'll work with, such as Akka and Play.
Your team may use PureConfig or Ficus as Scala wrappers for Typesafe Config, so you may want to
learn them, but you need to know Typesafe Config first in either case.
Internal
Scala Exercises
All exercises should have tests!
Pick the ScalaTest style your team prefers for unit tests, or specs2 unit specification style if your team
uses specs2.
Please review all exercises with your dev manager or the mentor they suggest
1. Use a trait to define a generic queue of strings with 'put' and 'get' methods, and create a
class that implements it using an array. Include tests.
2. Starting from the previous exercise, use a stackable trait to modify the behavior of 'put' so it
reverses each string (e.g. hello to olleh) before adding it to the queue. Include tests.
3. Write the ~= operator for comparing doubles. The operator should return true iff 2 doubles
are equal up to a small constant. The constant should be configurable but also have a
default. (hint: use implicit parameter) Include tests.
4. Implement GCD in Scala (hint: use tail recursion)
5. Write a clause that measures the run time of a block of code and prints it (also needs to
return the original output of the block):
timeit {
...
...
}
6. This could also be implemented using a function (hint: use call-by-name in function
signature)
7. Given a string containing words separated by space, find:
a. The longest word
b. The most common word
c. The most common letter
d. Create a map from letter to a set of words it appears in
8. Convert a list of strings to a list of all the characters in all the strings
9. Given the following code:
trait IntSet {
def incl(x: Int): IntSet
def contains(x: Int): Boolean
}
class EmptySet extends IntSet {
def contains(x: Int): Boolean = false
def incl(x: Int): IntSet = new NonEmptySet(x, new EmptySet, new EmptySet)
}
class NonEmptySet(elem: Int, left: IntSet, right: IntSet) extends IntSet {
def contains(x: Int): Boolean =
if (x < elem) left contains x
else if (x > elem) right contains x
else true
Internal
def incl(x: Int): IntSet =
if (x < elem) new NonEmptySet(elem, left incl x, right)
else if (x > elem) new NonEmptySet(elem, left, right incl x)
else this
}
10. Write methods union and intersection to form the union and intersection between two sets.
trait IntSet {
...
def union(x: IntSet): IntSet
def intersect(x: IntSet): IntSet
}
13. to return the given set without the element x. To accomplish this, it is useful to also
implement a test method
14. def isEmpty: Boolean
16.
17. Consider the following definitions representing trees of integers (Binary Search Tree). These
definitions can be seen as an alternative representation of IntSet:
abstract class IntTree
case object EmptyTree extends IntTree
case class Node(elem: Int, left: IntTree, right: IntTree) extends IntTree
18. Complete the following implementations of function contains and insert for IntTree’s by
using pattern matching on case classes.
def contains(v: Int): Boolean = ...
def insert(v: Int): IntTree = ...
19. Consider a function which squares all elements of a list and returns a list with the results.
Complete the following two equivalent definitions of squareList.
def squareList(xs: List[Int]): List[Int] = xs match {
case List() => ??
case y :: ys => ??
}
def squareList(xs: List[Int]): List[Int] = {
xs map ??
}
Internal
b. A function that gets optional Ints x, y, and z and if all are defined (Some(...)), returns
their product.
c. A function that gets a sequence of optional elements and returns the first that is not
None.
21. Given a list:List[Int] and map:Map[Int, Double], multiply all the numbers in the list with their
corresponding value in the map, and drop if don't exists
For example, list = [1,2,3,4], map = {1 -> 3, 3-> 5} ==> res = [3, 15]
22. Write a retry method that converts a method to a retry-able method.
However, you also need some way to specify how many times to retry and support sleep
between retries (hint: implicit arguments)
23. Design a class that is given a vector of numbers in the constructor and exposes:
Nothing should be calculated in the constructor of the class assume the calculation of x, y, z
can take a lot of time, and should only be done once (at most)
24. Add a method "median" to a Seq of integers so that s.median is the media of s for s of type
Seq[Int]
How can you add the same method for a sequence of doubles with minimal code
duplication?
25. Basic scalalab exercises https://github.com/scala-labs/scala-
labs/tree/master/labs/src/test/scala/org/scalalabs/basic
Internal
Concurrency in Scala
Our intro training course and this page mostly cover sequential programming. That's because
concurrency is a large topic, and there are many options available in Scala—your learning path from
here will branch depending on what you need in your team: Futures; Akka Actors; Rx and Reactive
Streams like Akka's, Monix, FS2; Cats Effect, etc. Ask your teammates for suggestions.
Learning Concurrent Programming in Scala is a solid reference that surveys many of these paradigms,
written by an authoritative source: one of the authors of standard library Futures and parallel
collections. The book should be available on O'Reilly Safari, ask your manager about how to access it.
There are a few paper copies available on BKK 22, bookshelf beside the pantry.
If you need to work with Futures (unless most of your development is on Spark, you probably will),
these are helpful places to start:
Git Training
Make sure you are familiar with all the things written here:
• https://www.atlassian.com/git/tutorials/viewing-old-commits/
• https://www.atlassian.com/git/tutorials/undoing-changes
• https://www.atlassian.com/git/tutorials/syncing
• https://www.atlassian.com/git/tutorials/rewriting-history
• https://www.atlassian.com/git/tutorials/using-branches
• https://www.atlassian.com/git/tutorials/merging-vs-rebasing
• https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/
Internal