Apply list of functions to value using Scala Cats - scala

in haskell I could do the following to a string
let f = sequence [id, reverse]
f "test"
I am at a bit of a loss how to approach this in a better method using Cats. I currently have something like
val f = List(fun1,fun2)
val data = "test"
f map {fun => fun(data)}
Is there an implementations of Sequence or SequenceU that can accomplish this using Cats?

It's more or less exactly the same, except that the syntax is a little different, you need some extra imports, and the generic version isn't as convenient since Scala's String isn't just an alias for a list of characters:
import cats.instances.function._, cats.instances.list._, cats.syntax.traverse._
val funcs: List[String => String] = List(identity, _.reverse)
val f = funcs.sequenceU
In Haskell sequence requires a Traversable instance for the outer type constructor of its argument, and a Monad instance for the inner type constructor. Cats's sequence is almost the same—Traversable is called Traverse (because the name Traversable is already taken by the standard library), and it requires an Applicative instance instead of Monad (which is a more accurate constraint—Haskell's sequence only requires a monad instance for historical reasons).
If you wanted you could just import cats.implicits._, but that brings in a lot of other stuff. The imports above provide the minimal type class instances and syntactic extensions you need.
You can use f, which is a String => List[String], like this:
scala> f("test")
res0: List[String] = List(test, tset)
Note that if you're on 2.12.1 and have the -Ypartial-unification compiler flag enabled, you can just write .sequence, not .sequenceU. Why you need the U on earlier Scala versions is a long story—see my blog post here for an explanation.

Related

Functions vs function pointers

Can someone explain the following to me:
scala> def squared(x: Int) = x * x
squared: (x: Int)Int
scala> val sq : (Int) => Int = squared
sq: Int => Int = <function1>
scala> sq.getClass
res111: Class[_ <: Int => Int] = class $anonfun$1
I understand this so far, squared is a function while sq is a function pointer.
But then I do this:
scala> squared.getClass
<console>:13: error: missing arguments for method squared;
follow this method with `_' if you want to treat it as a partially applied function
squared.getClass
^
Why can't I invoke getClass on squared ? After all, aren't functions 1st class objects ? Why do I need to do this for it to work ?
scala> squared(7).getClass
res113: Class[Int] = int
And I also get the same result for
scala> sq(5).getClass
res115: Class[Int] = int
Come to think of it, why do
scala>squared(5)
and
scala> sq(5)
produce the same result, even though one is a function, and the other a function pointer without needing to use a different syntax ?
Something akin to *sq(5) may have been clearer, no ?
The concept of a pointer isn't really relevant here, or in Scala (or the JVM) more generally. The difference between squared and sq is that squared is a method, and sq is a function.
Scala is (primarily) a language designed to be compiled to JVM bytecode. The JVM doesn't have first class functions, but it does have methods, which are associated either with an instance of a class (instance methods) or simply with the class itself (static methods). Methods in this sense are a fundamentally different kind of thing than objects to the JVM—they can't be passed as arguments to other methods, etc.
Because Scala is a functional language and functional languages are built on the idea of higher-order functions and first class functions more generally, the Scala language designers needed to be able to encode functions in a way that would work on the JVM. This is done via a Function1 class, and when you write something like this:
val sq: (Int) => Int = x => x * x
You are using Scala's syntactic sugar for creating instances of the Function1 class. These things are functions encoded as JVM objects, so they can be passed around and treated as first class things in the language.
Scala doesn't abandon the idea of methods, though. For reasons related in part to Scala's functional-OOP hybridity and in part to issues of performance, most Scala programs make extensive use of def definitions, which define methods, not "functions" in the sense of Function1. Scala provides a special conversion process (called eta expansion) by which methods can be treated as functions in many situations (including the right-hand side of your sq definition here).
If this all seems confusing, believe me, it is. You get used to it after a while, though (just get the idea of pointers out of your head as quickly as possible).
I understand this so far, squared is a function while sq is a function pointer.
Incorrect. Scala has neither explicit pointers nor function pointers
scala> (squared _).getClass
res4: Class[_ <: Int => Int] = class $anonfun$1
scala> sq.getClass
res5: Class[_ <: Int => Int] = class $anonfun$1
scala> :type squared _
Int => Int
scala> :type sq
Int => Int
Both have the same type. The difference is that functions which are defd do not live in the same namespace as vals or vars and code which refers to one is parsed differently from code which refers to the other.
Specifically, a reference to a val is an expression which can be evaluated. A reference to a defd function is not an expression and you can't apply operators like . which only apply to values.

Why do you need Arbitraries in scalacheck?

I wonder why Arbitrary is needed because automated property testing requires property definition, like
val prop = forAll(v: T => check that property holds for v)
and value v generator. The user guide says that you can create custom generators for custom types (a generator for trees is exemplified). Yet, it does not explain why do you need arbitraries on top of that.
Here is a piece of manual
implicit lazy val arbBool: Arbitrary[Boolean] = Arbitrary(oneOf(true, false))
To get support for your own type T you need to define an implicit def
or val of type Arbitrary[T]. Use the factory method Arbitrary(...) to
create the Arbitrary instance. This method takes one parameter of type
Gen[T] and returns an instance of Arbitrary[T].
It clearly says that we need Arbitrary on top of Gen. Justification for arbitrary is not satisfactory, though
The arbitrary generator is the generator used by ScalaCheck when it
generates values for property parameters.
IMO, to use the generators, you need to import them rather than wrapping them into arbitraries! Otherwise, one can argue that we need to wrap arbitraries also into something else to make them usable (and so on ad infinitum wrapping the wrappers endlessly).
You can also explain how does arbitrary[Int] convert argument type into generator. It is very curious and I feel that these are related questions.
forAll { v: T => ... } is implemented with the help of Scala implicits. That means that the generator for the type T is found implicitly instead of being explicitly specified by the caller.
Scala implicits are convenient, but they can also be troublesome if you're not sure what implicit values or conversions currently are in scope. By using a specific type (Arbitrary) for doing implicit lookups, ScalaCheck tries to constrain the negative impacts of using implicits (this use also makes it similar to Haskell typeclasses that are familiar for some users).
So, you are entirely correct that Arbitrary is not really needed. The same effect could have been achieved through implicit Gen[T] values, arguably with a bit more implicit scoping confusion.
As an end-user, you should think of Arbitrary[T] as the default generator for the type T. You can (through scoping) define and use multiple Arbitrary[T] instances, but I wouldn't recommend it. Instead, just skip Arbitrary and specify your generators explicitly:
val myGen1: Gen[T] = ...
val mygen2: Gen[T] = ...
val prop1 = forAll(myGen1) { t => ... }
val prop2 = forAll(myGen2) { t => ... }
arbitrary[Int] works just like forAll { n: Int => ... }, it just looks up the implicit Arbitrary[Int] instance and uses its generator. The implementation is simple:
def arbitrary[T](implicit a: Arbitrary[T]): Gen[T] = a.arbitrary
The implementation of Arbitrary might also be helpful here:
sealed abstract class Arbitrary[T] {
val arbitrary: Gen[T]
}
ScalaCheck has been ported from the Haskell QuickCheck library. In Haskell type-classes only allow one instance for a given type, forcing you into this sort of separation.
In Scala though, there isn't such a constraint and it would be possible to simplify the library. My guess is that, ScalaCheck being (initially written as) a 1-1 mapping of QuickCheck, makes it easier for Haskellers to jump into Scala :)
Here is the Haskell definition of Arbitrary
class Arbitrary a where
-- | A generator for values of the given type.
arbitrary :: Gen a
And Gen
newtype Gen a
As you can see they have a very different semantic, Arbitrary being a type class, and Gen a wrapper with a bunch of combinators to build them.
I agree that the argument of "limiting the scope through semantic" is a bit vague and does not seem to be taken seriously when it comes to organizing the code: the Arbitrary class sometimes simply delegates to Gen instances as in
/** Arbirtrary instance of Calendar */
implicit lazy val arbCalendar: Arbitrary[java.util.Calendar] =
Arbitrary(Gen.calendar)
and sometimes defines its own generator
/** Arbitrary BigInt */
implicit lazy val arbBigInt: Arbitrary[BigInt] = {
val long: Gen[Long] =
Gen.choose(Long.MinValue, Long.MaxValue).map(x => if (x == 0) 1L else x)
val gen1: Gen[BigInt] = for { x <- long } yield BigInt(x)
/* ... */
Arbitrary(frequency((5, gen0), (5, gen1), (4, gen2), (3, gen3), (2, gen4)))
}
So in effect this leads to code duplication (each default Gen being mirrored by an Arbitrary) and some confusion (why isn't Arbitrary[BigInt] not wrapping a default Gen[BigInt]?).
My reading of that is that you might need to have multiple instances of Gen, so Arbitrary is used to "flag" the one that you want ScalaCheck to use?

Why does Scala not have a return/unit function defined for each monad (in contrast to Haskell)?

What is the reason behind the design decision in Scala that monads do not have a return/unit function in contrast to Haskell where each monad has a return function that puts a value into a standard monadic context for the given monad?
For example why List, Option, Set etc... do not have a return/unit functions defined in the standard library as shown in the slides below?
I am asking this because in the reactive Coursera course Martin Odersky explicitly mentioned this fact, as can be seen below in the slides, but did not explain why Scala does not have them even though unit/return is an essential property of a monad.
As Ørjan Johansen said, Scala does not support method dispatching on return type. Scala object system is built over JVM one, and JVM invokevirtual instruction, which is the main tool for dynamic polymorphism, dispatches the call based on type of this object.
As a side note, dispatching is a process of selecting concrete method to call. In Scala/Java all methods are virtual, that is, the actual method which is called depends on actual type of the object.
class A { def hello() = println("hello method in A") }
class B extends A { override def hello() = println("hello method in B") }
val x: A = new A
x.hello() // prints "hello method in A"
val y: A = new B
y.hello() // prints "hello method in B"
Here, even if y variable is of type A, hello method from B is called, because JVM "sees" that the actual type of the object in y is B and invokes appropriate method.
However, JVM only takes the type of the variable on which the method is called into account. It is impossible, for example, to call different methods based on runtime type of arguments without explicit checks. For example:
class A {
def hello(x: Number) = println(s"Number: $x")
def hello(y: Int) = println(s"Integer: $y")
}
val a = new A
val n: Number = 10: Int
a.hello(n) // prints "Number: 10"
Here we have two methods with the same name, but with different parameter type. And even if ns actual type is Int, hello(Number) version is called - it is resolved statically based on n static variable type (this feature, static resolution based on argument types, is called overloading). Hence, there is no dynamic dispatch on method arguments. Some languages support dispatching on method arguments too, for example, Common Lisp's CLOS or Clojure's multimethods work like that.
Haskell has advanced type system (it is comparable to Scala's and in fact they both originate in System F, but Scala type system supports subtyping which makes type inference much more difficult) which allows global type inference, at least, without certain extensions enabled. Haskell also has a concept of type classes, which is its tool for dynamic polymorphism. Type classes can be loosely thought of as interfaces without inheritance but with dispatch on parameter and return value types. For example, this is a valid type class:
class Read a where
read :: String -> a
instance Read Integer where
read s = -- parse a string into an integer
instance Read Double where
read s = -- parse a string into a double
Then, depending on the context where method is called, read function for Integer or Double can be called:
x :: Integer
x = read "12345" // read for Integer is called
y :: Double
y = read "12345.0" // read for Double is called
This is a very powerful technique which has no correspondence in bare JVM object system, so Scala object system does not support it too. Also the lack of full-scale type inference would make this feature somewhat cumbersome to use. So, Scala standard library does not have return/unit method anywhere - it is impossible to express it using regular object system, there is simply no place where such a method could be defined. Consequently, monad concept in Scala is implicit and conventional - everything with appropriate flatMap method can be considered a monad, and everything with the right methods can be used in for construction. This is much like duck typing.
However, Scala type system together with its implicits mechanism is powerful enough to express full-featured type classes, and, by extension, generic monads in formal way, though due to difficulties in full type inference it may require adding more type annotations than in Haskell.
This is definition of monad type class in Scala:
trait Monad[M[_]] {
def unit[A](a: A): M[A]
def bind[A, B](ma: M[A])(f: A => M[B]): M[B]
}
And this is its implementation for Option:
implicit object OptionMonad extends Monad[Option] {
def unit[A](a: A) = Some(a)
def bind[A, B](ma: Option[A])(f: A => Option[B]): Option[B] =
ma.flatMap(f)
}
Then this can be used in generic way like this:
// note M[_]: Monad context bound
// this is a port of Haskell's filterM found here:
// http://hackage.haskell.org/package/base-4.7.0.1/docs/src/Control-Monad.html#filterM
def filterM[M[_]: Monad, A](as: Seq[A])(f: A => M[Boolean]): M[Seq[A]] = {
val m = implicitly[Monad[M]]
as match {
case x +: xs =>
m.bind(f(x)) { flg =>
m.bind(filterM(xs)(f)) { ys =>
m.unit(if (flg) x +: ys else ys)
}
}
case _ => m.unit(Seq.empty[A])
}
}
// using it
def run(s: Seq[Int]) = {
import whatever.OptionMonad // bring type class instance into scope
// leave all even numbers in the list, but fail if the list contains 13
filterM[Option, Int](s) { a =>
if (a == 13) None
else if (a % 2 == 0) Some(true)
else Some(false)
}
}
run(1 to 16) // returns None
run(16 to 32) // returns Some(List(16, 18, 20, 22, 24, 26, 28, 30, 32))
Here filterM is written generically, for any instance of Monad type class. Because OptionMonad implicit object is present at filterM call site, it will be passed to filterM implicitly, and it will be able to make use of its methods.
You can see from above that type classes allow to emulate dispatching on return type even in Scala. In fact, this is exactly what Haskell does under the covers - both Scala and Haskell are passing a dictionary of methods implementing some type class, though in Scala it is somewhat more explicit because these "dictionaries" are first-class objects there and can be imported on demand or even passed explicitly, so it is not really a proper dispatching as it is not that embedded.
If you need this amount of genericity, you can use Scalaz library which contains a lot of type classes (including monad) and their instances for some common types, including Option.
I don't think you're really saying that Scala's monads don't have a unit function - it's rather just that the name of the unit function can vary. That's what seems to be shown in the second slide's examples.
As for why that is so, I think it's just because Scala runs on the JVM, and those function have to be implemented as JVM methods - which are uniquely identified by:
the class they belong to;
their name;
their parameters types.
But they are not identified by their return type. Since the parameter type generally won't differentiate the various unit functions (it's usually just a generic type), you need different names for them.
In practice, they will often be implemented as the apply(x) method on the companion object of the monad class. For example, for the class List, the unit function is the apply(x) method on the object List. By convention, List.apply(x) can be called as List(x) too, which is more common/idiomatic.
So I guess that Scala at least has a naming convention for the unit function, though it doesn't have a unique name for it :
// Some monad :
class M[T] {
def flatMap[U](f: T => M[U]): M[U] = ???
}
// Companion object :
object M {
def apply(x: T): M[T] = ??? // Unit function
}
// Usage of the unit function :
val x = ???
val m = M(x)
Caveat: I'm still learning Haskell and I'm sort of making up this answer as I go.
First, what you already know - that Haskell's do notation desugars to bind:
Borrowing this example from Wikipedia:
add mx my = do
x <- mx
y <- my
return (x + y)
add mx my =
mx >>= (\x ->
my >>= (\y ->
return (x + y)))
Scala's analogue to do is the for-yield expression. It similarly desugars each step to flatMap (its equivalent of bind).
There's a difference, though: The last <- in a for-yield desugars to map, not to flatMap.
def add(mx: Option[Int], my: Option[Int]) =
for {
x <- mx
y <- my
} yield x + y
def add(mx: Option[Int], my: Option[Int]) =
mx.flatMap(x =>
my.map(y =>
x + y))
So because you don't have the "flattening" on the last step, the expression value already has the monad type, so there's no need to "re-wrap" it with something comparable to return.
Actually there is a return function in scala. It is just hard to find.
Scala slightly differs from Haskell in many aspects. Most of that differences are direct consequences of JVM limitations. JVM can not dispatch methods basing on its return type. So Scala introduced type class polymorphism based on implicit evidence to fix this inconvenience.
It is even used in scala standard collections. You may notice numerous usage of CanBuildFrom and CanBuild implicits used in the scala collection api. See scala.collection.immutable.List for example.
Every time you want to build custom collection you should write realization for this implicits. There are not so many guides for writing one though. I recommend you this guide. It shows why CanBuildFrom is so important for collections and how it is used. In fact that is just another form of the return function and anyone familiar with Haskell monads would understand it's importance clearly.
So you may use custom collection as example monads and write other monads basing on provided tutorial.

How do you use scalaz.WriterT for logging in a for expression?

How do you use scalaz.WriterT for logging?
About monad transformers
This is a very short introduction. You may find more information on haskellwiki or this great slide by #jrwest.
Monads don't compose, meaning that if you have a monad A[_] and a monad B[_], then A[B[_]] can not be derived automatically. However in most cases this can be achieved by having a so-called monad transformer for a given monad.
If we have monad transformer BT for monad B, then we can compose a new monad A[B[_]] for any monad A. That's right, by using BT, we can put the B inside A.
Monad transformer usage in scalaz
The following assumes scalaz 7, since frankly I didn't use monad transformers with scalaz 6.
A monad transformer MT takes two type parameters, the first is the wrapper (outside) monad, the second is the actual data type at the bottom of the monad stack. Note: It may take more type parameters, but those are not related to the transformer-ness, but rather specific for that given monad (like the logged type of a Writer, or the error type of a Validation).
So if we have a List[Option[A]] which we would like to treat as a single composed monad, then we need OptionT[List, A]. If we have Option[List[A]], we need ListT[Option, A].
How to get there? If we have the non-transformer value, we can usually just wrap it with MT.apply to get the value inside the transformer. To get back from the transformed form to normal, we usually call .run on the transformed value.
So val a: OptionT[List, Int] = OptionT[List, Int](List(some(1)) and val b: List[Option[Int]] = a.run are the same data, just the representation is different.
It was suggested by Tony Morris that is best to go into the transformed version as early as possible and use that as long as possible.
Note: Composing multiple monads using transformers yields a transformer stack with types just the opposite order as the normal data type. So a normal List[Option[Validation[E, A]]] would look something like type ListOptionValidation[+E, +A] = ValidationT[({type l[+a] = OptionT[List, a]})#l, E, A]
Update: As of scalaz 7.0.0-M2, Validation is (correctly) not a Monad and so ValidationT doesn't exist. Use EitherT instead.
Using WriterT for logging
Based on your need, you can use the WriterT without any particular outer monad (in this case in the background it will use the Id monad which doesn't do anything), or can put the logging inside a monad, or put a monad inside the logging.
First case, simple logging
import scalaz.{Writer}
import scalaz.std.list.listMonoid
import scalaz._
def calc1 = Writer(List("doing calc"), 11)
def calc2 = Writer(List("doing other"), 22)
val r = for {
a <- calc1
b <- calc2
} yield {
a + b
}
r.run should be_== (List("doing calc", "doing other"), 33)
We import the listMonoid instance, since it also provides the Semigroup[List] instance. It is needed since WriterT needs the log type to be a semigroup in order to be able to combine the log values.
Second case, logging inside a monad
Here we chose the Option monad for simplicity.
import scalaz.{Writer, WriterT}
import scalaz.std.list.listMonoid
import scalaz.std.option.optionInstance
import scalaz.syntax.pointed._
def calc1 = WriterT((List("doing calc") -> 11).point[Option])
def calc2 = WriterT((List("doing other") -> 22).point[Option])
val r = for {
a <- calc1
b <- calc2
} yield {
a + b
}
r.run should be_== (Some(List("doing calc", "doing other"), 33))
With this approach, since the logging is inside the Option monad, if any of the bound options is None, we would just get a None result without any logs.
Note: x.point[Option] is the same in effect as Some(x), but may help to generalize the code better. Not lethal just did it that way for now.
Third option, logging outside of a monad
import scalaz.{Writer, OptionT}
import scalaz.std.list.listMonoid
import scalaz.std.option.optionInstance
import scalaz.syntax.pointed._
type Logger[+A] = WriterT[scalaz.Id.Id, List[String], A]
def calc1 = OptionT[Logger, Int](Writer(List("doing calc"), Some(11): Option[Int]))
def calc2 = OptionT[Logger, Int](Writer(List("doing other"), None: Option[Int]))
val r = for {
a <- calc1
b <- calc2
} yield {
a + b
}
r.run.run should be_== (List("doing calc", "doing other") -> None)
Here we use OptionT to put the Option monad inside the Writer. One of the calculations is Noneto show that even in this case logs are preserved.
Final remarks
In these examples List[String] was used as the log type. However using String is hardly ever the best way, just some convention forced on us by logging frameworks. It would be better to define a custom log ADT for example, and if needed to output, convert it to string as late as possible. This way you could serialize the log's ADT and easily analyse it later programmatically (instead of parsing strings).
WriterT has a host of useful methods to work with to ease logging, check out the source. For example given a w: WriterT[...], you may add a new log entry using w :++> List("other event"), or even log using the currently held value using w :++>> ((v) => List("the result is " + v)), etc.
There are many explicit and longish code (types, calls) in the examples. As always, these are for clarity, refactor them in your code by extracting common types and ops.
type OptionLogger[A] = WriterT[Option, NonEmptyList[String], A]
val two: OptionLogger[Int] = WriterT.put(2.some)("The number two".pure[NonEmptyList])
val hundred: OptionLogger[Int] = WriterT.put(100.some)("One hundred".pure[NonEmptyList])
val twoHundred = for {
a <- two
b <- hundred
} yield a * b
twoHundred.value must be equalTo(200.some)
val log = twoHundred.written map { _.list } getOrElse List() mkString(" ")
log must be equalTo("The number two One hundred")

What are the biggest differences between Scala 2.8 and Scala 2.7?

I've written a rather large program in Scala 2.7.5, and now I'm looking forward to version 2.8. But I'm curious about how this big leap in the evolution of Scala will affect me.
What will be the biggest differences between these two versions of Scala? And perhaps most importantly:
Will I need to rewrite anything?
Do I want to rewrite anything just to take advantage of some cool new feature?
What exactly are the new features of Scala 2.8 in general?
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 takes T as 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 Map is an alias in Predef for collection.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 traits MapLike, but this is really an implementation detail.
Reaping the Benefits
Replace some method overloading with named and default parameters.
Use the generated copy method 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 List to Seq or Iterable or Traversable. 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.
You can find here a preview of new feature in Scala2.8 (April 2009), completed with recent this article (June 2009)
Named and Default Arguments
Nested Annotations
Package Objects
#specialized
Improved Collections (some rewrite might be needed here)
REPL will have command completion (more on that and other tricks in this article)
New Control Abstractions (continuation or break)
Enhancements (Swing wrapper, performances, ...)
"Rewriting code" is not an obligation (except for using some of the improved Collections), but some features like continuation (Wikipedia: an abstract representation of the control state, or the "rest of computation" or "rest of code to be executed") can give you some new ideas. A good introduction is found here, written by Daniel (who has also posted a much more detailed and specific answer in this thread).
Note: Scala on Netbeans seems to work with some 2.8 nightly-build (vs. the official page for 2.7.x)
VonC's answer is hard to improve on, so I won't even try to. I'll cover some other stuff not mentioned by him.
First, some deprecated stuff will go. If you have deprecation warnings in your code, it's likely it won't compile anymore.
Next, Scala's library is being expanded. Mostly, common little patterns such as catching exceptions into Either or Option, or converting an AnyRef into an Option with null mapped into None. These things can mostly pass unnoticed, but I'm getting tired of posting something on the blog and later having someone tell me it's already on Scala 2.8. Well, actually, I'm not getting tired of it, but, rather, and happily, used to it. And I'm not talking here about the Collections, which are getting a major revision.
Now, it would be nice if people posted actual examples of such library improvements as answers. I'd happily upvote all such answers.
REPL is not getting just command-completion. It's getting a lot of stuff, including the ability to examine the AST for an object, or the ability to insert break points into code that fall into REPL.
Also, Scala's compiler is being modified to be able to provide fast partial compilation to IDEs, which means we can expect them to become much more "knowledgable" about Scala -- by querying the Scala compiler itself about the code.
One big change is likely to pass unnoticed by many, though it will decrease problems for library writers and users alike. Right now, if you write the following:
package com.mystuff.java.wrappers
import java.net._
You are importing not Java's net library, but com.mystuff.java's net library, as com, com.mystuff, com.mystuff.java and com.mystuff.java.wrappers all got within scope, and java can be found inside com.mystuff. With Scala 2.8, only wrappers gets scoped. Since, sometimes, you want some of the rest to be in Scope, an alternative package syntax is now allowed:
package com.mystuff.factories
package ligthbulbs
which is equivalent to:
package com.mystuff.factories {
package lightbulbs {
...
}
}
And happens to get both factories and lightbulbs into scope.
Will I need to rewrite anything?
def takesArray(arr: Array[AnyRef]) {…}
def usesVarArgs(obs: AnyRef*) {
takesArray(obs)
}
needs to become
def usesVarArgs(obs: AnyRef*) {
takesArray(obs.toArray)
}
I had to visit the IRC channel for that one, but then realized I should have started here.
Here's a checklist from Eric Willigers, who has been using Scala since 2.2. Some of this stuff will seem dated to more recent users.
* Explicitly import from outer packages *
Suppose we have
package a
class B
Change
package a.c
class D extends B
to
package a.c
import a.B
class D extends B
or
package a
package c
class D extends B
* Use fully qualified package name when importing from outer package *
Suppose we have
package a.b
object O { val x = 1 }
Change
package a.b.c
import b.O.x
to
package a.b.c
import a.b.O.x
* When explicitly specifying type parameters in container method calls, add new type parameters *
Change
list.map[Int](f)
to
list.map[Int, List[Int]](f)
Change
map.transform[Value](g)
to
map.transform[Value, Map[Key, Value]](g)
* Create sorted map using Ordering instead of conversion to Ordered *
[scalac] found : (String) => Ordered[String]
[scalac] required: Ordering[String]
[scalac] TreeMap[String, Any](map.toList: _*)(stringToCaseInsensitiveOrdered _)
* Import the implicit conversions that replace scala.collection.jcl *
* Immutable Map .update becomes .updated *
*** Migrate from newly deprecated List methods --
* elements
* remove
* sort
* List.flatten(someList)
* List.fromString(someList, sep)
* List.make
*** Use List methods
* diff
* iterator
* filterNot
* sortWith
* someList.flatten
* someList.split(sep)
* List.fill
* classpath when using scala.tools.nsc.Settings *
http://thread.gmane.org/gmane.comp.lang.scala/18245/focus=18247
settings.classpath.value = System.getProperty("java.class.path")
* Avoid error: _ must follow method; cannot follow (Any) => Boolean *
Replace
list.filter(that.f _)
with
list.filter(that f _)
or
list.filter(that.f(_))
>
>
>
* Migrate from deprecated Enumeration methods iterator map *
Use Enumeration methods values.iterator values.map
* Migrate from deprecated Iterator.fromValues(a, b, c, d) *
Use Iterator(a, b, c, d)
* Avoid deprecated type Collection *
Use Iterable instead
* Change initialisation order *
Suppose we have
trait T {
val v
val w = v + v
}
Replace
class C extends T {
val v = "v"
}
with
class C extends {
val v = "v"
} with T
* Avoid unneeded val in for (val x <- ...) *
* Avoid trailing commas *