Study note of the chapter 15, 16, 17, and 18 of the book: Programming In Scala, 4th Edition.

Chapter 15: Case Classes and Pattern Matching

A case class/object is syntactic suguar that defines a class and its companion object. The benefits:

  • a factory method has the same number of class parameters.
  • all class parameters are val constructor parameters.
  • methods of toString, hashCode, equals and copy.
  • a companion object defines apply and unapply methods.
  • a case class can be used in pattern matching.
  • a case class is serializable.
  • a case class can extend another regualr class or a trait.

The disadvantages are some overheads and not inheritable.

A match is an expression that matches a select to a sequence of alternatives evaluated in the defined order. An alternative includes a pattern and one or more expressions. Kinds of patterns include:

  • wildcard pattern: _ matches any object.
  • constant pattern: a literal or any simple name not starting with a lower case letter.
  • variable pattern: a simple name starts with a lower case letter.
  • constructor pattern: a class constructor.
  • sequence pattern: a sequnce type like List or Array. Use _* as the last element to match any number of elements.
  • tuple pattern: a tuple.
  • typed pattern: a case name: Type pattern. Because of type erasure, there is no way to match type arguments of a generic type. Array[T] is a special case that keeps its type argument at runtime.
  • variable binding: in constructor pattern, use x @ pattern to bind a pattern to a vairable.

A pattern guard comes after a pattern and start with an if. A pattern is linear that a pattern variable may only appear once in a patter.

A sealed class cannot have any new subclasses except the ones defined in the same file. The compile will check that a match is exhaustive for a sealed class. To disable the exhaustivity checking, use @unchecked annotation to a selector expression like (e: @unchecked) match {}.

Patterns can be used in other places than the match expression:

  • Variable defintions: destruction assignment to multiple variables.
  • case sequences as partial function literals. By default, a variable assigned to a function literal has a type of complete function. To make it a partial function type, declare its type as PartialFunction[...].
  • for expression: a pattern used in a for expression may filter over the generated values. Only matching values are kept.

Chapter 16: Working with List

16.1 List

The List is a immutable, recursive data type. List elements are homogeneous ann covariant.

Nil is List() and has a type of List[Nothing]. The pattern of a list can be List(a, b, c) that is an extractor pattern or x :: xs wthat is a constructor pattern.

16.2 Methods

List methods: head, tail, isEmpty, ::, :::, length, init, last, reverse, drop, take, splitAt, apply, indices, flatten, zip, unzip, toString, mkStrin, addString, iterator, toArray, copyToArray, map, flatMap, foreach, filter, partition, find, takeWhile, dropWhitl, span, forAll, exists, foldLeft, foldRight, sortWith.

Methods of the List companion object: apply, range, fill, tabulate, concat.

16.3 Effeciency

List operation is more efficient working on the head of a list.

Because ::: takes time proportional to its first argument, it more effecient to use foldRight with :::.

lazyZip is used when the intermeidate value is useless.

16.4 Type inference

Scala uses a local, flow-based type inference that is optimized for the OO subtyping.

Chapter 17 Working with Other Collections

17.1 Sequences

  • List is immutable and good at head operations.
  • Array is mutable with fixed size and good for random access.
  • ListBuffer is mutable and provides constant time append (+=) and preappend (+=:) operations.
  • ArrayBuffer is mutable and has changable size.
  • StringOps is a rich type wrapper for String that adds methods such as exists etc.

17.2 Sets and Maps

They have both immutable and mutable types that share the same name. The default are immutable HashSet and HashMap. All support +, -, ++, --, +=, ++=, -= and --=. The immutable map and set have optimized implementation when size is less than 5.

TreeSet and TreeMap are sorted sets and maps that use an implicit Ordering trait instance.

Immutable types are preferred for easier to reason and more compact space. The +=, ++=, -=, --= works for var varaibles of immutable types.

To convert between different collection types(including between immutable and mutable types), use either to method or toList/toArray method.

17.3 Others

Tuple doesn’t inherit from Iterable because its elements may be of different types.

Use _1 and _2 methods to access the first and second elements.

val x, y = z is a multiple defintion that is the same as val x = z; val y = z. The right hand size is evaluated for each assignment.

Chapter 18: Mutable Objects

A setter x is a method named as x_=.

val t: T = _ initializes t with the default value of T.