Skip to content

Latest commit

 

History

History
176 lines (139 loc) · 6.05 KB

day3.org

File metadata and controls

176 lines (139 loc) · 6.05 KB

Day 3

Generic Types

Aka type parameters, parametric polymorphism

We know has to write a specific type. Analogous to method parameters

  • define them on a type (trait, class) or a method
  • Type is not known at the point of definition (can be any specific type, but we don’t know what that type is), but must be known (concrete) at the point of use (i.e. when using a concrete instance)
  • Declaration and use of type parameters
    • Declare like a method parameter: declare a name for types: [A] for method parameters: (a: A)
    • Use of a type parameter: refer to the parameter type parameter A or method parameter: a
  • Scope: declared on a type it is visible within that type, declared on a method only visible within that method

Detour into companion objects

  • apply method

Functions

Literal syntax

Type syntax

Functions as objects

  • methods are not objects
  • you can pass a function to a method or function, but you cannot pass a method to a method or function
  • you can return a function from a method or function, but you cannot return a method from a method or function
  • you can give a function a name with val
  • calling a function is calling the apply method on it
  • functions have other methods for composition
  • convert a method to a function by using methodName _ or methodName(_)
  • traits Function0 etc that functions extend. Very rare to use these directly. Usually use the type syntax above.

Validation

Collection Classes

Collection classes live in scala.collection.immutable or scala.collection.mutable. Some are already imported (part of Predef).

  • Sequences
  • Maps
  • Constructing
  • Querying
  • Transforming

Sequences

Retain order of elements (usually order that are inserted) List, ArrayBuffer, Vector

Constructing

empty: method on the companion object to construct an empty container Vararg constructor: List() List(1,2,3), etc. Preprend and append elements: +:, :+ If a method works on both mutable and immutable collections it is immutable.

Aside: operator notation vs method call notation a.b(c) is equivalent to a b c

Method names that end with a colon (:) are right associative when used as operators a.b:(c) is equivalent to c b: a

Querying

size gets size / length isEmpty, nonEmpty, etc.

find: finds the first element that matches a predicate (a function from element to boolean). Returns an Option (because there may be no match). filter: finds all the elements that match a predicate. Returns a collection of the same type.

Transformation

map: transforms every element in the collection with the provided function. Number of elements and order does not change.

F[A] map (A => B) = F[B] type equation. F is the container type and does not change. The element type can change.

flatMap: we can think of it as a map followed by a flatten.

F[A] flatMap (A => F[B]) = F[B] type equation. F is the container type and does not change. The element type can change.

getCustomersForLastMonth: List[Customer] getOrdersForCustomer(customer: Customer): List[Order]

To get all the orders for the last month

getCustomersForLastMonth.flatMap(c => getOrdersForCustomer(c))

groupBy: Groups data using a key returned by the function parameter.

foldLeft and foldRight: these are structural recursion

Maps

Maps associate keys with values Two type parameters: Key and Value

Map("a" -> 1, "b" -> 2, "c" -> 3): Map[String, Int] with String keys and Int values

Note: a -> b is a tuple, equivalent to (a, b)

Maps work a lot like sequences (that have a map method, for example)

mapValues to map just the values get to get a value by key (returning an Option) + to add key-value pairs to the Map

val mm1: HashMap[String, Int] = HashMap(“a” -> 1, “b” -> 2) val mm2: HashMap[String, Any] = mm1

mm2 += (“c” -> “surprise!”)

mm1.get(“c”)

Immutable Collections

Use structural sharing for efficiency. Sometimes called persistent data structures.