Taking the Leap
When you migrate, the compiler can provide you with some safety nets.
- Compile your old code against 2.7.7
with-deprecation, and follow the
recommendations from all deprecation
warnings. -
Update your code to use
unnnested packages. This can be done
mechanically by repeatedly running
this regular expression search
replace.s/^(package com.example.project.*)\.(\w+)/$1\npackage $2/g -
Compile with 2.8.0 compiler, using paranoid command line options
-deprecation -Xmigration -Xcheckinit -Xstrict-warnings -Xwarninit -
If you receive errors the error
could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T], you need to add an implicit parameter (or equivalently, a context bound), on a type parameter.Before:
scala> def listToArray[T](ls: List[T]): Array[T] = ls.toArray <console>:5: error: could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T] def listToArray[T](ls: List[T]): Array[T] = ls.toArray ^After:
scala> def listToArray[T: Manifest](ls: List[T]): Array[T] = ls.toArray listToArray: [T](ls: List[T])(implicit evidence$1: Manifest[T])Array[T] scala> def listToArray[T](ls: List[T])(implicit m: Manifest[T]): Array[T] = ls.toArray listToArray: [T](ls: List[T])(implicit m: Manifest[T])Array[T]Any method that calls
listToArray, and itself takesTas a type parameter, must also accept the Manifest as an implicit parameter. See the Arrays SID for details. -
Before too long, you’ll encounter an error like this:
scala> collection.Map(1 -> 2): Map[Int, Int] <console>:6: error: type mismatch; found : scala.collection.Map[Int,Int] required: Map[Int,Int] collection.Map(1 -> 2): Map[Int, Int] ^You need to understand that the type
Mapis an alias in Predef forcollection.immutable.Map.object Predef { type Map[A, B] = collection.immutable.Map[A, B] val Map = collection.immutable.Map }There are three types named
Map— a read-only interface:collection.Map, an immutable implementation:collection.immutable.Map, and a mutable implementation:collection.mutable.Map. Furthermore, the library defines the behaviour in a parallel set of traitsMapLike, but this is really an implementation detail.
Reaping the Benefits
- Replace some method overloading with named and default parameters.
-
Use the generated
copymethod of case classes.scala> case class Foo(a: Int, b: String) defined class Foo scala> Foo(1, "a").copy(b = "b") res1: Foo = Foo(1,b) - Generalize your method signatures from
ListtoSeqorIterableorTraversable. Because collection classes are in a clean hierarchy, can you accept a more general type. - Integrate with Java libraries using Annotations. You can now specify nested annotations, and have fine-grained control over whether annotations are targeted to fields or methods. This helps to use Spring or JPA with Scala code.
There are many other new features that can be safely ignored as you start migrating, for example @specialized and Continuations.