scala notes
- 1. val and var
 - 2. Classes and Objects
 - 3. singleton objects
 - 4. Operators
 - 5. operatros are methods
 - 6. Class
 - 7. Inheritance
 - 8. Build-in control structures
 - 9. Function and Closures
 - 10. Control Abstraction
 - 11. Curring
 - 12. By-name parameters
 - 13. Traits
 - 14. Imports
 - 15. Assertions and Unit Testing
 - 16. Case Classese && Pattern Matching && Extractors
 - 17. Collections
 - 18. List & Sets and Maps
 - 19. collection hierarchy
 - 20. Type Parameterization
 - 21. variance annotations
 - 22. Abstract Members
 - 23. Implicit Conversions and Parameters
 - 24. Annotations
 - 25. Modular Programming Using Object
 - 26. Actors and Concurrency
 
val and var
val: you could not reassign the variant, but whether the variant is mutable or not depends on its own type.
the parameters are vals( functional programming)
Classes and Objects
singleton objects
- a class and its companion object can access each other’s private members.
 - singleton objects inheriting from classes and traits in Chp 13
 - you should inherit from 
Applicationonly when your program is relatively simple and single-threaded. 
Operators
operatros are methods
- infix: 
a + b:(a).+(b) - prefix: 
+,-,!and~.(short hand ofunary_+…) - postfix: methods that take no arguments
 - operator associativity: 
:right ro left.
no matter what associativity an operator has, its operands are always evaluated left to right 
Class
- the Scala compiler will place the code for the initializers of the fields into the primary constructor in the order in which they appear in the source code.
 - abstact classes
a class with abstract memeber must iself be declared abstract. - using parameterless methods(when no parameter), it supports the uniform access principle, which says that client code should not be affected by a decision to implement an attribute as a field or method.
encouraged: define methods that take no parameters and have no side effects as parameterless methods. 
Inheritance
- subtyping means that a value of the subclass can be used wherever a value of the superclass is required.
 scala has two namespaces:
1. values(fields, methods, package, and singleton objects)types(class and trait names)
so you could overriding a parameterless method with a field.
factory object
a factory object contains methods that construct other objects. Clients would then use these factory methods for object construction rather than constructing the objects directly withnewNullis a subclass of every reference class.Nothingis a subtype of every other type.- value equality: 
==, reference equality:eq. How to write an equality method ?
1. override `equals` in class `Any`: `override def equals(other: Any) = ...`- override 
hashCodemethod - when 
equalsandhashCodeare defined in terms of mutable fields, you may need more things to do. to deal with the equality relationships between class and its subclass, you need to add one more method
def canEqual(other: Any): Booleanfor non-final class. For the example bellow, if the subclassColoredPointoverridescanEqual, then the instance ofColoredPointandPointis not equal, otherwise, it can be equal to aPointinstance.//one exampleclass Point(val x: Int, val y: Int) {
override def hashCode = 41*(41 + x) + y
override def equals(other: Any) = other match {case that: Point => (that canEqual this) && (this.x == that.x) && (this.y == that.y) case _ => false}
def canEqual(other: Any) = other.isInstanceOf[Point]
}
`
- override 
 
Build-in control structures
- Try to challenge 
whileloops in your code in the same way you challengesvars. If there isn’t a good justification for a particularwhileordo-whileloop, try to find a way to do the same thing without it. - For expression
usingforexpression may make things clearer`persons withFilter (p => !p.isMale) flatMap (p =>
//clear(p.children map (c => (p.name, c.name) ) )
for (p <- persons; if !p.isMale; c <- p.children)yield (p.name, c.name)</pre> in fact, everyforexpression can be expressed in terms of the three higher-order functionsmap,flatMapandwithFilter. So if you definemap,flatMap,withFilterandforeachmethods for your data type, your data types could supportforexpression. If you just define a subset of these methods, then your data type would support a subset of all possiblefor` expressions. live without
breakandcontinue, tail-call.1. If the solution is tail recursive, there won’t be any runtime overhead to be paid.(_tail-call optimization_)- tail-call optimization is limited to situations in which a method or nested function calls itself directly as its last operation.
 
Function and Closures
- programs should be decomposed into many small functions that each do a well-defined task.
 - first-class functions
Every function value is an instance of some class that extends one of severalFuntionNtraits in packagesscala. EachFunctionNtrait has anapplymethod used to invoke the function. - partially applied functions
someNumbers.forach(sum _)
you could leave off the-here (only when a function type is expected). - closures
when a closure accesses some variable that has several different copies as the program runs, the instance used is the one that was active at the time the closure was created. 
Control Abstraction
Curring
By-name parameters
<pre>`def byNameAssert(predicate: => Boolean) = 
    if (assertionsEnabled && !predicate)
        throw new AssertionError
def boolAssert(predicate: Boolean) = 
    if(assertionEnabled && !predicate)
        throw new AsserstionError
//evaluate (5>3) before the call to boolAssert
boolAssert(5 > 3)
//the expression (5>3) is not evaluated before the call to byNameAssert.
byNameAssert(5 > 3)
`</pre>
Traits
A trait differs with a class:
1. no parameterssupercalls are dynamically bound
- if a trait delcares a superclass, then it can only be mixed into a class that also extends that superclass.
`trait Doubling extends IntQueue {
}abstract override def put(x: Int) { super.put(2*x) }</pre>supercall is dynamically bound, it will work so long as the trait is mixed in _after_ another trait or class that gives a concrete definition to the method.abstract override` (only used for traits) means that the trait must be mixed into some class that has a concrete definition ot the method. - traits as stackable modifications    
val queue = (new BasicIntQueue with Filtering with Incrementing)
traits further to the right take effect first. when determine thesupercall, use linearization!4. If it might be reused in multiple, unrelated classes, use trait;
if you want to inherit from it in Java code, use abstract class;
if you plan to distribute it in compiled form, lean towards an abstract class;
if efficiency is very important, lean towards using a class. 
Imports
flexible:
* may appear anywhere- may refer to objects(singleton or regular) in addition to packages
 - let you rename and hide some of the imported members
`import Fruits.{Apple => McIntosh} //rename apple //import all Fruits except for Apple import Fruits.{Apple => _, _} ` 
- scope of protection
private[X]orprotected[X]means that access is private or protected “up to” X, where X disignates some enclosing package, class or singleton object. - package objects
Each package is allowed to have one package object. 
Assertions and Unit Testing
to be read
Case Classese && Pattern Matching && Extractors
case classes
1. _case class_ addes a factory method with the name of class.2. all arguments in the parameter list of a case class implicitly get a `val` prefix, so they are maintained as fields.- the compiler addes methods 
toString,hashCode,equalsto case class. - the compiler adds a 
copymethod for making modified copies. 
- the compiler addes methods 
 - a variable pattern matches any object, Scala binds the variable to whatever the object is.
To treat a lowercase identifier as a constant in a pattern match, use back-tickpi. - typed patterns
`def generalSize(x: Any) = x match { case s: String => s.length case m: Map[_, _] => m.size case _ => -1 } `because of _type erasure_, you could not chek `case m: Map[Int, Int]`. Only exception to the erasure rule is arrays. `case a: Array[String]` . The element type of an array is stored with the array value, so you can pattern match on it. variable binding:`expr match { case Unop("abs", e @ Unop("abs", _) ) => e case _ => } ` - A sealed class cannot have any new subclasses added except the ones in the same file. If we want Scala compiler help to detect missing patterns, we should make the superclass of case classes sealed.
 case sequences as partial functions6. patterns in
forexpressions
for (Some(fruit) <- results) println(fruit)
Extractors
A extractor is an object that has a method called
unapplyorunapplySeq.`object Domain { def apply(parts: String*): String = parts.reverse.mkString(".") def unapplySeq(whole: String): Option[Seq[String]] = Some(whole.split("\\.").reverse) } dom match { case Domain("org", "acm") => println("acm.org") case Domain("net", _*) => println("a .net domain") `- Compared with case classes, extractors is representation independence, that’s to say, patterns have nothing to do with the data type of the object that’s selected on. While case classes also have their advantages: short code and more efficient.
 
Collections
List & Sets and Maps
- type inference algorithm:
Type inference is flow based. In a method applicationm(args), it first checks whether the methodmhas a known type. If it has, that type is used to infer the expected type of the arguments.msort((x: Char, y: Char) => x > y)(abcdb) abcde sortWith (_ > _)
the type ofabcdeisList[Char], so we do not need to write it explicitly, could just use_. - When designing a polymorphic method that takes some non-function arguments and a funtion argument, place the function argument last in a curried parameter list.( The methods’ correct instance type can be inferred from the non-function arguments).
 scala.collection.mutable.Set()andscala.collection.mutable.Map()usually uses hash talbe. While forscala.collection.immutable.{Set(), Map()}, it depends how many elements you pass to it. If there are more than 5 elements, then they use hash methods.
collection hierarchy
- the difference between 
TraversableandIterable?
see discussion in stackOverflow - All collections except streams and views are strict. The only way to go from a strict to a lazy collection is via the 
viewmethod. The only way to go back is viaforce. a view is a special kind of collection that represents some base collection, but implements all of its transformers lazily.
1. Using view could avoiding intermediate results.- create a subwindow for mutable sequences to update selectively some elements of that sequence.
`findRalindrome(words.view take 10000) //1 //2 val arr = (0 to 9).toArray val subarr = arr.view.slice(3, 6) do_something(subarr) // update partial of arr `
 
- create a subwindow for mutable sequences to update selectively some elements of that sequence.
 - Factoring out common operations
CanBuildFrom: check this post - integrate a new collection class into the framework
1. decide whether the collection should be mutable or immutable- pick the right base traits for the collection
 - inherit from the right implementation trait to implement most collection operations
 - if you want 
mapand similar operations to return instances of your collection type, provide an implicitCanBuildFromin your class’s companion object. 
 
Type Parameterization
variance annotations
- covariant(
+), contravariant(-), nonvariant - In a purely functional word, many types are natureally covariant. However, the situation changes once you introduce mutable data. In fact, if a generic parameter type appears as the type of a method parameter, the containing class or trait may not be covariant in that type parameter.
 - In scala, arrays are nonvariant.  you could cast an array of 
Ts to an array of any supertype ofT`val a1 = Array("abc") val a2: Array[Object] = a1.asInstanceOf[Array[Object]] ` - lower bound
`class Queue[T](private val leading: List[T],
}private val trailing: List[T] ) { def enqueue[U >: T](x: U) = new Queue[U](leading, x :: trailing)//...</pre> You coud append anOrangeto aQueue[Apple]. The result will be aQueue[Fruit]`.s - Liskov Substitution Principle: It is safe to assume that a type 
Tis a subtype of a typeUif you can substitute a value of typeTwhereer a value of typeUis required. The principle holds ifTsupports the same operations asUand ll ofT‘s operations require less and provides more than the corresponding operations inU.
When you write the function typeA => B, Scala expands this toFunction1[A,B].`trait Function[-S, +T] {
}def apply(x: S): T</pre> TheFunction1in the trait is contravariant in the function argument typeSand covariant in the result typeT`, because argument are somthing that’s required, whereas results are something that’s provided. - upper bound    
def orderedMergeSort[T <: Ordered[T]](xs: List[T]): List[T] = { ... }
Means the element type of the list passed toorderedMergeSortmust be a subtype ofOrdered. - object private data
`class Queue[+T] private(
){ … }private[this] var leading: List[T], private[this] var trailing: List[T]</pre> Here typeTis a covariant type, butleadingandtrailingare variable, there should be a contravariant position, there will be a compiler error. But if we markprivate[this]`, the compiler has special handling in it’s variance checking for this case. 
Abstract Members
- one example
`trait Abstract { type T //abstract type def transform(x: T): T val initial: T var current: T } ` - For abstract vals, it could only be implemented by a 
valdefinition; For abstract method, it may be implemented by both concrete method definitions and concretevaldefinitions. initializing abstract vals
`trait RationalTrait {val numerArg: Int val denomArg: Int}
//anonymous class
new RationalTrait {val numerArg = 1 val denomArg = 2 require(denomArg != 0)//exception ...}
//pre-initialized
new {val numerArg = 1 * x val denomArg = 2 * x} with RationalTrait
</pre> Here we first define a traitRationalTraitwith abstract vals, then we have an _anonymous class_ that mixes in the trait. The anonymous class is initialized _after_ theRationalTrait, so the values ofnumerArganddenomArgare not available during the initialization ofRationalTrait(i.e. theses two are 0). so therequireinvocation will fail. so, a class parameter argument is evaluated _before_ it is passed to the class constructor(unless by-name). An implementingval` definition in a subclass, by contrast, is evaluated only after the superclass has been initialized. Two solutions:* pre-initialized- lazy vals
 
- path-dependent types
`class DogFood extends Food
class Dog extends Animal {
}type SuitableFood = DogFood override def eat(food: DogFood) {}
val bessy = new Dog
val lassie = new Dog</pre>bessy.SuitableFoodis a _path-dependent type_ and it’s the same type aslassie.SuitableFood. while <pre>class Outer {
}class Inner
val o1 = new Outer
val o2 = new Outer</pre>o1.Inneris a different type aso2.Inner. They are subtypes ofOuterInner`. - structural subtyping
you get a subtyping relationship simply because two types have the same members.
class Pasture {* If you want to define a _Pasture_ class that contains animals that eat grass, you could write the type `Animal { type SuitableFood = Grass }`. so you could define _Pasture_ like this:val animals: List[ Animal {type SuitableFood = Grass} ] = Nil }- If you want to group together a number of classes that were written by someone else.    
def using[T <: { def close(): Unit }, S](obj: T) (operation: T => S) = { val result = operation(obj) obj.close() result }
No base type is specified, so Scala would useAnyRefautomatically, and the typeTmust supportclose()method. 
 - If you want to group together a number of classes that were written by someone else.    
 
Implicit Conversions and Parameters
rules for implicits:
1. Marking Rule: Only definitions marked `implicit` are available.- Scope Rule: An inserted implicit conversion must be in scope as a single identifier, or be associated with the source or target type of the conversion(i.e. companion object).
 - One-at-a-time Rule: Only one implicit is tried.
 - Explicits-First Rule: Whenever code type checks as it is written, no implicits are attempted.
 
Where implicits are tried:
1. implicit conversion to an expected type`//1
implicit def int2double(x: Int): Double = x.toDouble
var i: Double = 1
//2 receiver
implicit def intToRational(x: Int) = new Rational(x, 1)
1 + oneHalf //intToRational(1) + oneHalf
//3 def maxListT(implicit orderer: T => Ordered[T]): T = elements match{ case List() => throw new IllegalArgumentException("empty list!") case List(x) => x case x :: rest => val maxRest = maxList(rest) //(orderer) is implicit if (x > maxRest) x //orderer(x) is implicit else maxRest }maxList(List(1,5,10,3)) //res: Int = 10
//view bound
def maxList2T <% Ordered[T] : T = { …. }
//upper bound
def maxList3[T <: Ordered[T] }(elements: List[T]): T = { … }2. Converting the receiver: interoperating with new types; simulating new syntax 3. implicit parametersview bound: We could use view bound to shorten the method header.
The difference between view bound and upper boundsT <: Ordered[T]is that upper bounds require thatTis a subtype ofOrdered[T], however, for view bound, it only requires that T can be treated as anOrdered[T]. So we could pass aList[Int]tomaxListandmaxList2but no tomaxList3.multiple conversions
choose a more sprcific one. One implicit conversion is more spercific than another if one of the following applies:1. The argument type of the former is a subtype of the latters’s- Both conversions are methods, and the enclosing class of the former extends the enclosing class of the latter.
 
Annotations
- standard annotations:
@deprecated@volatitle@serializable@SerialVersionUID@transient
`@scala.reflect.BeanProperty@tailrec@unchecked@native` 
Modular Programming Using Object
- self type
check this post in StackOverflow. - singleton type
A singleton type is extremely specific and holds only one object. check this post 
Actors and Concurrency
not too much to record, the example showed in Programming in Scala is worth understanding.