(Created August, last updated December)

Think of this post as a set of revision notes I can skim to remind myself of the hundreds of pages I’ve read, the many blogs and examples and so on.  It is terse.

Scala needs no crib sheet, do the coursera course and read Scala for the impatient,  and then study and practice for months. But, writing notes helps me out.

http://www.scala-lang.org/api https://class.coursera.org/progfun-005/wiki/CheatSheet

http://www.tutorialspoint.com/scala/scala_classes_objects.htm

Coursera 4.2 - objects everywhere. The example with implementing a boolean is not easy to comprehend.

Referential Transparency: Pure functional programs don’t have side effects.

Expect to read and practice and read some more - and also you can forget all the stupid Java frameworks which have come into existence over the last 15 years and start to embrace the scala frameworks… Oh.

Some general points

Scala lets you write bad code - unstructured files with thousands of lines of stupidly unreadable code. Java tries really hard to stop you doing this, and yet in java it still happens. So Scala gave up - bad devs will code write only code, ie the poor folks who come later will not be able to read it. If you look at scala and cannot understand it then blame the dev - tell him/her. Tell their boss.

Ignore the functional stuff to start with, instead get your mind around the collections, in particular

foreach side effects only - ie each member will do something creating a side effect, like printing to the screen
Map Applies a function to each member and returns something the same size
filter using a predicate (ie a boolean result) to remove some of the elements
zip Join two to form a collection of tuples
partition split a list based on a predicate
find returns the first element that matches a predicate
drop & dropWhile remove the first elements
foldLeft from the starting element, do stuff and pass an accumulator. This is a scala thing which says recursion is good, using the stack is good - and its optimised so the stack frame is reused if you do it right...details.
foldRight from the last element, do stuff and pass an accumulator.
flatten if you have a list containing lists, then it flattens this to a single list with the first one first, then the contents of the next one etc
flatMap take a function and apply it then flatten all the results.

Currying

Functions that return functions after Haskell Curry. “Sometimes it makes sense to let people apply some arguments to your function and others later” - twitter Scala School.

How to read

// This is syntatic sugar, a function which takes a function and returns a function has a special form rather than
// sum( f: Int => Int) : (x: Int, y:Int) => Int = {
// can be written instead as:
sum(f: Int => Int) (x: Int, y:Int) : Int

This is read from the left, so

(Int => Int) => (x:Int, y:Int) => Int, but function types are right associative, which means you read it with invisible () like this (Int => Int) => (( x:Int, y:Int) => Int)

(Int => Int) is a function. This function returns a function which takes two arguments. which itself returns an int.

so, sum(takes a function with an Int param which returns an Int), and sum() will return a function which takes two Int’s that returns an Int.

sum(f: Int => Int) (x: Int, y:Int) : Int sum(f: Int => Int) returns ((x: Int, y:Int) : Int) sum( param is a function) returns ( a function )

BUT, if you then call the function, you can think of it like this

sum( cube ) (1,3) so, sum(cube) is called first, and that returns the function, which is called with params 1,3, ie (sum(cube)) (1,3)

Syntax examples

 

abstract class List[T] {
  def foldLeft[U](z: U)(op: (U, T) => U): U = this match {
    case Nil => z
    case x :: xs => (xs foldLeft op(z, x))(op)
  }
}

 

So, list has a type parameter [T]. So list can be a list of things - we don’t care what their type is. foldLeft is a function, and has a type parameter U, so we know there are parameter or return types we are not fixing - again any old object will do. foldLeft has a parameter z, and is a curried partial function, which means that it will return a function taking two parameters, one will be of type U (matching the parameter z) and one will be of type T which is the same type as the list will have within it. This function will itself return a type of U.

General notes

Existential Types: http://www.drmaciver.com/2008/03/existential-types-in-scala/

_ wild card...
REPL Read-Evaluate-Print-Loop, use :paste to enter multi line
Function
Procedure A function which returns no value, return type us Unit, ie called for its side effect such as printing something to screen.
Method
Higher order Method A method which takes another method as a parameter
=>parameter Pass by name, so its only evaluated when it is used. eg streams where the tail is only evaluated on demand.
Unit Same as void in java
Nothing A special type for teh throws expression.
Generator Sequence fed into a loop for instance
Guard Masks out values from a generator
for (i <- 1 to 3; j<- 1 to 3 if i !=j) print((10*i + j)+ " ")
Comprehension Converts into a collection using yield.
for (i <- 1 to 3) yield I
Lazy Not initialised until it is used.
Type projection To make inner class owned by any instance of the outer. Syntax is Outer#Inner when using the Inner.
Companion Object Same name as the class, holds static methods, in same source file as the class.
lt:(T, T) => Boolean Usually means the less than function. ie lt is of type, a function taking two params of type T returning a Boolean. Try to use math.Ordering[T] rather than write your own lt:
/: foldLeft
:\ foldRight
& Intersect
setA | setB Union
&~ Diff
Predicate Just means something that returns true or false

Pass by name

When in a parameter list use =>, which means that the parameter is not evaluated to a value until it is used. This is extremely important for Streams, where the parameter is a function, so rather than (for instance)  a recursive function being called to pass by value, instead the name of the function is passed in and is only evaluated when it is used.

e.g. you have a stream to generate numbers, with a filter on it or some termination condition which is applied  to each value as the stream produces it. You have an infiniate stream producing values, and it does this by recursion. BUT, it is never called that many times, and the pass by name allows you to design it in this way.

The Underscore

In scala this is a special character which tells the compiler to infer what I mean - so if there can only be one object, rather than me naming it, giving it a type and so on, can the compiler do that for me.

(_*_)

(x, y) => (x+y) ie a function taking params x and y is defined as x + y.

( _ + 2 )
def adder(m:Int, n:Int) = m+n
val add2 = adder(2, _:Int)
add2(3)

This gives you a value of 5. ie this is Partial application, an unnamed magical wildcard according to twitters Scala Scool.

s map ( _ / 2)

ie map applies the operation to all elements, in this case _ means the thing within the sequence - list, set etc

Unit

Equivalent to void in Java

Assignments have Unit value, so x=y=1 is BAD. ie y=1 is fine, but it in turn has Unit value, so x=Unit.

asInstanceOf isInstanceOf

x.isInstanceOf[T] x.asInstanceOf[T]

These are methods on class Any.

You really SHOULD NOT USE THEM unless interoperating with Java.

Scala class hierarchy

 scala.Any              // defines Methods: '==', '!=', 'equals, 'hashCode', 'toString'
     scala.anyVal       // base type of primitives
         scala.Double
         scala.Float
         ...
     scala.anyRef       // Alias of java.lang.Object
         scala.Object
             scala.Iterable
                 scala.Seq
                     scala.List
         java.lang.String

 scala.Nothing           // bottom of type hierarchty, subtype of every other type, 
                         // eg abnormal termination as an element type of empty 
                         //collections
     scala.Null          // subtype of all reference types, type of null is Null.  
                         // Not of value types

Also, conversion relationships exist between many of the anyVal subtypes.

Subtyping and Generics

In a trait you can def stuff. In a class which extends you can val it.

trait List[T] {
     def isEmpty: Boolean
     def head T
     def tail: List[T]
 {
 class Cons[T](val head: T, val tail: List[T]) extends List[T] {
     def isEmpty = false
 }
 class Nil[T] extends List[T] {
     def isEmpty = true
     def head: Nothing = throw new NoSuchElementException("Nil.head")
     def tail: Nothing = throw new NoSuchElementException("Nil.tail")
 }
 def singleton[T](elem: T) = new Cons[T](elem, new Nil[T])

 singleton[Int](1)
 singleton[Boolean](true)

But, scala can deduce the type params, so singleton(1) singleton(true)

So, the trait used def, but Cons used fields (in the constructor they are vals which is a shortcut).

In the Nil, Nothing is fine as its the base type of everything.

type erasure means type params do not affect evaluation in Scala.

val var

val is an immutable

var is a mutable

IO

stdout

 print("Answer")
 println("Answer")

stdin

 readInt
 readDouble
 readByte
 readShort
 readLong
 readFloat
 readBoolean
 readChar

Loops

1 - 10 means a range, ie it creates a range

You can inject the range using <-, so

for (i <- expr) will loop i through the expression.

If you are looping through a string or array you do NOT want the last index, so use until

val s = "Hello"
var sum=0
for (i <- 0 until s.length)
 sum += s(i)

or

 for (ch <- "Hello") sum += ch
Generators again
variable <- expression

You can have multiple generators in one for loop, eg

 for (i <- 1 to 3; j<- 1 to 3) print((10*i + j)+ " ")

Each Generator can have a guard, which masks out values, so you can do

 for (i <- 1 to 3; j<- 1 to 3 if i !=j) print((10*i + j)+ " ")
Definitions embedded in the loop
for (i <- 1 to 3; from =4-i; j <- from to 3) print ((10 * i + j) + " ")

Longer syntax uses braces, you can use ; or you could use newline and no ;

for { i <- 1 to 3
      from = 4-i
      j <- from to 3 }
Yield = for comprehension
for (i <- 1 to 3) yield i

or an expression

for (i <- 1 to 3) yield "Person "+i

Functions and methods

Method - generates an object

function - doesn’t.

Function
def abs(x: Double) = if (x=0) x else -x

Return type not needed for function if can be derived and is not recursive.

def fac(n: Int): Int = if (n <= 0) 1 else n * fac(n-1)
Default parameter values
def decorate(str: String, left: String = "[", right: String="]") = left+str+right

When calling a function you can name the parameters, and change the order

decorate( right=">", left="<", str="Angles")
Variable number of args
def sum(args: Int*) = {
 var result =0
 for (arg <- args) result += arg
 result
}
def caitaliseAll(args: String*) = {
 args.map { arg => arg.capilatize }
}
Convert a generator into a sequence of arguments _*
val s = sum(1 to 5: _*)

or for recursive with variable arguments

def recursiveSum(args: Int*) : Int = {
  if (args.length ==0) 0
  else args.head + recursiveSum(args.tail : _*)
}

Collections

http://docs.scala-lang.org/overviews/collections/overview.html

This has the best function guide - which I list briefly below http://docs.scala-lang.org/overviews/collections/trait-traversable.html

Simple guide to operations

// takes function of elem => U where elem is type of the iterable, 
// and just applies function to each
xxx.foreach  

// join two together
++

// apply function and produce new collection
map, flatmap, collect	

// conversions
toArray, toList, toIterable, toSeq, toIndexedSeq, toStream, toSet, toMap

copyToBuffer, copyToArray

hasDefiniteSize	// collections can be infinite, or finite, this tells you, eg stream
isEmpty, nonEmpty, size	

// in unordered versions these operation can return pretty random elemenets, used ordered sets etc
head, last, headOption, lastOption, and find

// obtain sub traversables, possibly using predicates etc
tail, init, slice, take, drop, takeWhile, dropWhile, filter, filterNot, withFilter

Seq

The Seq trait represents sequences. A sequence is a kind of iterable that has a length and whose elements have fixed index positions, starting from 0. http://docs.scala-lang.org/overviews/collections/seqs.html

head: the first item tail: everything else, ie 2nd item onwards

+: Add element to front

:+ Add element to the end

sorted, sortWith, sortBy

Lots of others but these are the commmon ones

Arrays

Use Array if length is fixed, and ArrayBuffer if it varies.

To transform an array use for (elem

val nums=new Array[Int](10)  // array of 10 integers all 0.
val s = Array("Hello", "World") // no need of new, length 2 etc
s(0) = "Goodbyte"  // use () to access members, not []

ArrayBuffers are variable length.

 import scala.collection.mutable.ArrayBuffer
 val b=ArrayBuffer[Int]()
 b += 1
 b += (1,2,3,4)
 b ++= Array(8,13,21) // ++= means append a collection
 b.trimEnd(5)


 b.insert(2, 6) // 2 is the insert posion, 6 is the data to insert.
 b.insert(2, 6,7,8)
 b.remove(2)
 b.remove(2,3) // from pos 2 remove the next 3, starting with 0 pos...
 b.toArray

 for (i &lt;- 0 until (a.length, 2)) // 0 to length, every 2nd one.

 (0 until a.length).reverse // reverse a string

 for (elem <- a) // dont need the index, just the element itself

 val result = for (elem <- a) yield 2 * elem // comprehension yields a collection
 // (array gives an array, arraybuffer gives an arraybuffer)

Multi-Dimensional

val matrix = Array.ofDimDouble // 3 rows 4 cols matrix(row)(column) = 4 // ie ()()

Sum, Sort

.sum, .max are all build in.

try this:

val b = ArrayBuffer(1,7,2,9)
val bSorted = b.sorted( _ < _)

Ordered is a trait that allows sorting.

scala.util.Sorting.quickSort(a)

List, Folds

A list can have operators which work by inserting an operator between each item in the list and the next item on the list.

ReduceLeft - only works on non empty lists

FoldLeft - takes an accumulator as the first param, and an operator

abstract class List[T] {
	def reduceLeft(op: (T, T) => T): T = this match {
		case Nil	=> throw new Error("Nil.reduceLeft")
		case x :: xs	=> (xs foldLeft x)(op)
	}
	def foldLeft[U](z: U)(op: (U, T) => U): U = this match {
		case Nil	=> z
		case x :: xs	=> (xs foldLeft op(z, x))(op)
	}
}

Note can also use /: for foldleft andd :\ for fold right

Option & Some

Any time you may get some value or a null, use an Option, which is a return type meaning it can be None or Some. ie there is no Null, in Scala we use

Option( Person ) human = people.get("Jonathan")
if (human.isDefined) println("Jonathan is here")

Better to say

println( people.getOrElse("Jonathan", "no Jonathan, boo hoo"))

can match case statements with None

Map

 val scores=Map("Alice" -&gt; 10, "Bob" ->3, "Cindy" ->8)  // creates immutable Map[String, Int]
 val scores=Map(("Alice" , 10), ("Bob", 3), ("Cindy", 8)) // not prefered, they prefer =&gt;

 // Mutable version
 val scores=new scala.collection.mutable.HashMap[String, Int]

 val bobsScore = scores.getOrElse("Bob", 0)    // This is a short cut to the line below
 val bobsScore = if (scores.contains("Bob")) scores("Bob") else 0

 // get returns an Option which is either Some(value for key) or None

 // assignment is done with left brackets
 scores("Bob") = 10
 scores("Fred") = 7

 //OR
 scores += ("Bob" -> 10, "Fred" -> 7)
 scores = scores - "Alice"   // removes an element

 scores.keySet
 scores.values
 for ((key, value) <- scores) print (key+":"+value)

 // To reverse keys and values try

 for ((key, value) &lt;- scores) yield (value, key)
 scala.collection.immutable.SortedMap
 scala.collection.mutable.LinkedHashMap

Tuples

Useful for returning multiple values from functions.

Look at zipping, ie joining two arrays together to form an array of 2 element tuples.

Classes

Scala source files can contain multiple classes, and all of them are public.

Getters Setters
// Scala synthesises getters and setters, foo (getter) and foo_ (setter)
var foo

// Scala only does getter
val foo

// provide a mutator, so no getters and setters, just your own mutator
private var value=0

/**
 * Scala code can use = or leave it off (if its Unit type).  
 * Between scala versions the style guide changed and the inventor has regrets...
 * more importantly for you, they may change Scala in a future release and just
 * drop some features, could be a risk....
 */
class Silly(var value:Int) {
  def increment1() { value += 1 }   // unit type can ignore the =, bad practice
  def increment1() = { value += 1 }
  def increment2() = value += 1
}

// No braces needed in the definition, don't need braces to call it either
def current = value

// Object-private. Accessing someObject.value is not allowed
private[this] var value = 0

You can use pattern matching to extract values from a pair, and tuples are case classes containing 2 or 3 or 4 or…. number of values. eg

val (label, value) = pair

could be written as

val label = pair._1
val value = pair._2

So, within the tuple the values are stored in fields called _1, _2 etc.

To view
scalac Person.scala
javap -private Person

You will see foo_$eq(int), JVM doesn't allow = in method name, so replaces with $eq
Case Classes

These are important! Its terse, it allows for pattern matching, it is not OO in the Java sense - but no one cares, embrace them.

Rather than adding a display() function to every subclass of displayable, in scala you could have a single function which pattern patches on the class and displays it in the correct way. As well as this, case classes (and objects) give you lots of free stuff - equals, hashcode, toString, copy methods, all params are val’s (imutable members), the companion object containing the static apply() and unapply methods.

Notes apply() means you can create a the class without using new. unapply() means you can use the class in pattern matching

Imagine you have lots of small java classes, say they are all FixFields (or some micro type), well in java you have a package with 400 tiny classes in, in scala you have a single file and 400 lines +1 for the base class and you get the same result.

When your case class has no parameter list use a case object.

Case class wierdness:

If you was case class parameters which do not get the magic val, etc then you can do this wierdness:

case class Boy(girlfriend: String)(shoesize: Int)

So the shoesize has no accessor etc - you could stick val infront to give it some…. and so on, apparently there are other language features which no normal human should use, makes your code unreadable.

Java compatable getters/setters

annotate as @BeanProperty to get java like getters and setters.

Constructors

Have to have a primary constructor. Every auxilary constructor must start with either a call to another auxilary or to the primary.

If you don’t define a primary constructor then it is there anyway, with no params.

Primary constructor

The parameters are given after the class definition:

class Person(val name: String, val age: Int) {
  println("Just constructed");
}

Params of the primary constructor turn into fields that are initialised with the construction parameters

You can elimitate many auxilary constructors using default arguments.

class Person(val name: String = "", private var age: Int =0) {
}

You can make the parameter a field - ie private by not using val or var, same as private[this]val.  If it is not used in any methods etc then the compiler could optimise it away? ie just params in the ctor.

class Person(name: String = "", age: Int =0) {
}
Private primary constructor

Only callable from auxilary constructors:

class Person private(val id: Int) {
}

Inner classes

They are owned by each instance, not like in Java where they are owned by the outer class.

So, if you create multipl instances of the class, each in a different instance then they are not of the same type - they are part of their owning instance.

BUT, if you want them to be compatible you can use type projection. This would for example mean “a Member of any Network”

class Network (
  class Member(val name: String) {
    val contacts=new ArrayBuffer[Network#Member]
  }
  ...
}

Ref to outer class

As in java Network.this.    Or, you can alias it

class Network(val name: String) {
  outer =>
    class Member(val name:String) {
      println(outer.name);
      println(Network.this.name);
    }
}

Singleton - still considered bad design

object Accounts {
  private var uniqueId = 0;
  def newUniqueId() { uniqueId +=1; uniqueId }
}

Accounts.newUniqueId();

Constructor called when it is first used.  Cannot have constructor arguments.

Note that the statment Singleton - still considered bad design came from some book or web site that I was skimming so I wrote it down. I guess its better to say that in Scala, unlike in Java, the companion object means that Objects are everywhere. You no longer need to go with having everything in a class instance.  Having said that, since scala loves immutability, then having Objects with var members is not a great idea… so, to generate an increasing count the above object is horrible, and is a bad idea. Read up on Akka, and alot of this hand wringing becomes even more irrelevant. Stick state in an Actor and walk away.

Companion objects

Don’t have static methods inside the class, stick them in the object of the same name.

Default Object inherit from class

object Foo extends bar("Do nothing") {
}

In effect you are using the singleton to define a global object which can be reused everywhere.

Apply methods

Define these in the companion object, and use them without needing the new keyword.

object Accounts{
     def apply(initialBalance: Double) = new Account(new UniqueNumber(), initialBalance)
}
Usage
val acct = Account(10000.0)

Main method

Use the App trait and you don’t need a main method

object Hello extends App {
  // args are available as the args property of App trait
  println("Hello World")
}

//Verbose version
object Hello {
  def main(args: Array[String]) {
    println("Hello World")
  }
}

scala -Dsacla.time Hello Fred

Displays the elapsed time

Sealed

A sealed class may not be directly inherited, except if the inheriting template is defined in the same source file as the inherited class. However, subclasses of a sealed class can be inherited anywhere.

Sealed traits can also be used as a replacement for enums

sealed trait Validity
case object Valid extends Validity
case object Invalid extends Validity

No enumeration, but an Enumeration trait (see Sealed above)

Forget about enums - the fact you want them means you are not thinking scala yet.

Object MyEnum extends Enumeration {
  val Red, Yellow, Green = Value
}

which is a shortcut for

Object MyEnum extends Enumeration {
  val Red=Value
  val Yellow=Value
  val Green = Value
}

ie each Value is an inner class, which you can give params as well BUT enumerations in scala are a bit crap.

Packages

You can nest packages, but people usually don’t - ie inside one class you could have nested package definitions. When you are in a package hierarchy, if your import uses a package chain (ie x.y.z) then you can only see things in your package, not the ones preceding.  But, if you do

package x.y
  package z

The you can see every thing in y and in z.

There is also the package object itself, where folks typically define package scope constants

package com.horstmann.impatient
  package object people {
    val defaultName = "John Q. Bloggs"
  }
  package people {
    class person {
      var name=defaultName // a constat from the package
   }
 }

Import

Use _ to import all classes, or all members of a class or object - like static import in java.

imports do NOT have to be at the top of a file - you can put them within a class or method which means you can use wildcard imports in smaller scope and worry less about conflicts.

import selectors let you pull in some classes rather than the entire package.
import java.awt.{Color, Font}
import java.util.{HashMap => JavaHashMap}  // selector syntax can rename imported classes.
import scala.collections.mutable._         // so HashMap is the scala one, and JavaHashMap redefined above.

Scala implicitely imports

     import java.lang._
     import scala._
     import Predef._

Note that the imports override previous ones in order, rather than conflicting.

Classes and stuff

getClass.getName works

final means cannot be overridden - val makes something immutable, so final on a field is different than Java.

You have to use override.

abstract class Person {
  def id: Int
}
class Student(override val id: Int) extends Person
  // student Id is simply provided in the constructor

A def can override another def

A val can override another val or a parameterless def

A var can only override an abstract var

isInstanceof Accepts nulls, returns false, tests if of that class or is a subclass

asInstanceOf Converts a reference to a subclass reference

classOf To test is if a class, but will be false if a subclass

BUT, pattern matching is better

p match {
  case s: Employee =&gt; ...
  case _ => // wasnt an employee
}

Protected

Protected is accessable from subclass, but NOT from other classes in this package (not like java)

protected[this] restricts to current object

Type, polymorphic variables (ie java generics, but more generally, just type)

 [+T]     Covariant, means C[T'] is a subclass of C[T]
          ie class Covarient[+A]; val cv: Covariant[AnyRef] = new Covariant[String]
 [-T]     Contravarient, C[T] is a subclass of C[T']
          ie class Contravarient[-A]; val cv: Covariant[String] = new Covariant[AnyRef]
          note:function parameters are contravariant. If you need a function that takes a Bird
          and you have a function that takes an Chicken, that function would choke on a Duck. But
          a function that takes an Animal is OK
 [T]      Invarient C[T] and C[T'] are not related
 List[B]  ie a list of generic type
 List[B >: T]    this specifies that B as a superclass of T
 def count(l: List[_]) = l.size
          Known as 'quantification', it is wildcard, and replaces the heavy handed syntax:
          def count(l: List[T forSome { type T }]) = l.size

 There is a list operator called ::(elem T) that returns a new List with elem prepended.

Cons, or ::

:: This is call cons.

eg p :: p2 means p cons p2, or a list with head p, tail of p2.

you can use in pattern matching, eg for lists

case y :: ys =>

i.e.
xs match {
  case List() => println("Empty list")
  case (x :: xs1) => println("Head element is "+x+" tail (ie the rest) is "+xs1)
}

Existential types

You have a function which takes a collection of stuff. You dont care what the stuff is and you don’t want the function signature to say that you care - eg adding a type parameter.

So you use an existential type, ie I want an array, but I dont care whats in it.

     T forSome { type T; }
 eg
     def foo(x : Array[T] forSome { type T}) = println(x.length)
 eg
     def foo(x : Array[T] forSome { type T  println(y.length))

Operators

Infix binary

Infix operators are binary operators - ie 2 params.

     1 to 10, where 1 is implicit and 10 is explicit.
     1.to(10)

     1 -> 10
     1.->(10)

Unary

Unary operators have one param. If it follow the argument it is a postfix operator. eg +,-,!,~ are prefix operators.

They are converted to calls to methods called unary_{operator} ie -a os same as a.unary_-

Postfix operators have lower precedence than infix operators

Left associative operators, ie evaluated left to right, eg a+b+c = (a+b)+c

Right associative operators must end in : eg :: is an operator for forming lists. So 1::2::Nil = 1::(2::Nil) And the operator is a method on the right param ie 2::Nil means Nil.::(2)

Scala has shortcuts in syntax to call methods called update and apply. ie f(arg1, arg2,…) = value is the same as f.update(arg1, arg2,…,value) or scores(“Bob”)=100 //calls scores.update(“Bob”, 100) val bobscore=scores(“bob”) // calls scores.apply(“Bob”)

Apply

apply is used in companion objects to avoid needing new(..

ie class Fraction(n: Int, d:Int) {…} Object Fraction{ def apply(n:Int, d:Int) = new Function(n, d) }

so can now do Fraction(3,4) rather than new Fraction(3,4)

Unapply

Unapply takes an object and extracts values from it.

var Fraction(a,b) = Fraction(3,4) * Fraction(2,5)

or

val Name(first, last) = author // calls Name.unapply(author)

They return an Option[ (String, String) ] or return None. It can also return a Some(…) for a single value

Implicit parameters

If you have a typed class (ie generic) and you want to have an ordering function from math.Ordering[T] passed into to, then the word implicit means that the compiler will attempt to find a function in Ordering which matches the derived type from the actual params which were passed in. ie If your paramiterised type is called with Int’s and the last parameter is an def msortT(implicit ord: Ordering[T]): List[T] = { ie msort takes a List of T’s and an ordering function from Ordering for type T’s. When you call this function you do not need to call it with the ordering function. ie compiler will synthesis the parameter, and if it can’t then its an error.