Skip to content

Instantly share code, notes, and snippets.

@mitchwongho
Last active May 16, 2016 05:52
Show Gist options
  • Save mitchwongho/73794d308796d5d3bd1a to your computer and use it in GitHub Desktop.
Save mitchwongho/73794d308796d5d3bd1a to your computer and use it in GitHub Desktop.
Essential Scala - Notes

Essential Scala - Notes

Classes, Objects and Traits

/* A class is an abstraction over objects */
/* constructor args declared using val to expose publicly and can declare default values */
class Foo(val arg1: Long, val arg1: Double, val arg3: Int = 0) {
  val someValue: Int = ??? /* public, immutable */
  var someVariable: Long = ??? /* public, mutable */
  def apply(arg1: Int) = ??? /* applies shorthand e.g instanceOfFoo(46) */
  def Method1: Int = ???
  def Method2: String = ???
}

/* A class is instantiated using the 'new' keyword */
val instanceOfFoo = new Foo(123L, 456.67)

object MySingleton {
  ... /* contains same body as what can be declared in a `class` */
}
/* A companion-object are declared in _same_ file as companion-class, and share the same name */
class Person(val name: String, val age: Int)

/** 
 * The companion-object methods are like Java static methods, but not exposed in class objects.
 * Use companion-objects to implement multiple constructor using `apply` method
 */
object Person {
  def apply(val name: String, val dob: java.util.Date): Person = {
    new Person(name, Person.getAge(dob))
  }
  /* returns an age */
  def getAge(val date: Date): Int = ???
}
/** 
 * case-classes are super classes:
 * - a field for each constructor value
 * - default toString() method
 * - sensible equals() and hashCode() methods
 * - a copy() method. Leverages constructor keywords concept
 * - default apply() method. Same signature as class constructor
 * - used for pattern-matching
 */
case class Male(name: Sting, age: Int)
case class Female(name: String, age: Int)

val john = Male("John Doe", 21)
val jane = john.copy(name="Jane Doe")
/* Traits are abstractions over classes. Mixture of Java Interface and Abstract-class*/
seal trait Visitor {
  def id: Long
  def createdAt: java.util.Date
  def age: Long = ??? /* now - createdAt */
}

final case class Anonymous(id: Long, createdAt: Date = new Date()) extends Visitor
final case class User(id: Long, email: String, createdAt: Date = new Date()) extends Visitor
/**
 * Traits: Best practice
 * - Use `def` over `val` to define values
 * - Seal your traits. Enforces that subtypes be declared in same file
 * - Final your case classes
 */

5.3 Modelling Data With Traits

5.3.1 The Has-a (Logicial AND) Pattern

This pattern can be described as:

A has a B and a C e.g. Visitor has an ID and an Email

and can be modelled as

case class A(b: B, c: C)

or

trait A {
  def b: B
  def c: C
}

5.3.2 The Is-a (Logical OR) Pattern

This pattern can be described as

A is a B or C for example Feline is a Lion or Tiger

and can be modelled as

sealed trait A
final case class B() extends A
final case class C() extends A

5.3.3 Algebraic Data Types

Data that can be expressed by either of the two patterns above are regarded as Algebraic Data Types.

5.5 Structural Recursion

Structural recursion is the decomposition of algebraic data types. Structural recursion can be applied using polymorphasim or pattern matching.

5.5.1 Structural Recursion using Polymorphasim

This pattern is commonly found in OO

Product-type (Logical OR) pattern

The structural resursive pattern for product-type data structures can be applied as follows

/** 
 * Suppose you have a class that you want deconstruct into it's parts,
 * simply define an abstract method in the base trait and implement it
 * in a concrete implementation
 **/
sealed trait A {
  def foo: String = "I'm an A"
}
final case class B extends A {
  override def foo: String = "I'm a B"
}

Sum-type (Logical AND) pattern

The structural resursive pattern for sum-type data structures can be expressed as

/**
 * Suppose you have a class that satisfies the sum-type (logical AND) algebraic data type
 * pattern, and you want to deconstruct it into it's parts, you can simply refer to it's
 * part e.g you can define a method (f) and refer to values `b` and `c` in `f`
 **/
case class A(b: B, c: C) {
  def f: F = ??? //you can access b and c
}

5.5.2 Structural Recursion using Pattern-Matching

/**
 * Suppose you have a class that satisfies the product-type (logical-OR) pattern. 
 * Using pattern-matching to deconstruct the class, match on the constructors
 */
case class A(b: B, c: C)

object someClassADeconstructor {
  def f(a: A): F = a match {
    case A(b, c) => ??? //you can access b and c
  }
}

/**
 * Suppose you have a class that satisfies the sum-type (logical-AND) pattern. 
 * Using pattern-matching to deconstruct the class, match on the type
 */
sealed trait A
final case class B(arg1: Int) extends A
final case class C(arg2: String) extends A

object someClassDeconstructor {
  def f(a: A): F = a match {
    case B(arg1) => ???  // you can access arg1
    case C(arg2) => ???  // you can access arg2
  }
}

5.6 Recursive Data

5.6.1 Recursive Algebraic Data Types Pattern

/**
 * Recursive ADTs consist of atleast two cases: a base case and a recursive case
 */
sealed trait BaseTrait
final case class BaseCase extends BaseTrait
final case class RecursiveCase(recursive: BaseTrait) extends BaseTrait

// example of 
def f( r: BaseTrait ): Int = r match {
  case BaseCase => 0 //some terminating value aka _identifier_
  case RecursiveCase( base ) => f(base)
}

6 Sequence Computations

6.1 Generics and Functions

/**
 * Generics can be applied to classes, traits and methods. 
 * The syntax [A, B , C] is called a type parameters.
 **/
trait Name[A](...) {...} 
case class Name[A](...) {...}

def generic[A](arg: A): A

6.1.2 Generic Algebraic Data Type

6.1.2.1 Invariant Generic SUM-Type Patten

If A of type T is a B and C

sealed trait A[T]
final case class B[T] extends A[T]
final case class C[T] extends A[T]

6.2 Functions

6.2.1 Function Types

Function types are written like (A, B) => C where A and B are parameter types, while C is the result type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment