The simplest way to work with the exercises is to get to SBT's REPL:
./activator
Once inside, In order to execute the whole test set:
> test
If you want to run only one test, just type this:
> testOnly fr.xebia.scala.StepXXX
Lets imagine that we have the following function
val sum: (Int, Int) => Int = _ + _
val result sum(1, 2) // result should be 3
But we split the parameters in order to reuse the first block. By using curried
we can transform an existing
function into a curried function
. So, by doing this
val sumCurried = sum.curried
val result = sumCurried(1)(2) // result should be 3
The following example show the relations beetween classes, traits and objects
trait SomeLikeAnInterfaceAndAbstractClass {
def aSimpleOperation = println("I'm an implementation")
}
trait anotherTrait {
def operation (param : Int) : Int
}
class MyClassLikeInJava (value: Int) extends SomeLikeAnInterfaceAndAbstractClass with anotherTrait {
override def operation (param : Int) : Int = param * value
}
object MySingletonInstance extends anotherTrait {
override def operation (param : Int) : Int = param * 2
}
You can use like this
new MyClassLikeInJava(2).operation(3) // should be 6
MySingletonInstance.operation(3) // should be 6
There are several ways to create list in scala.
- We can call the constructor directly
val list = List(1, 2, 3)
- Or we can call the
::
function to chain the different elements
val list = 1 :: 2 :: 3 :: Nil
Traversing a list means we need to handle at least two special cases:
-
The end of the list specified by the keyword Nil
-
The other cases, indicated by the pattern composed of a head and a tail, head :: tail
The easiest way to handle those cases is by using a pattern matching on the list.
def sum(list: List[Int]): Int = list match {
case Nil =>
0 /* we arrived to the end of the list */
case head :: tail =>
/* get the value from 'head' and handle recursively the other cases */
head + sum(tail)
}
Options atre strongly typed containers to represent a potentially "null" value. Can have any of the following values:
-
Some(actualValue)
, for exampleval num = Some(5)
-
None
, for example:val num2 = Option.empty[Int]
orval num3 = None
You can verify its value by the following means:
num2 match {
case Some(actualValue) => println(actualValue)
case None => println("No value")
}
val result1 = num2.getOrElse(0)
val result2 = num2.get // may fail if value not present
val result3 = num3.orElse(anotherOption).getOrElse(lastChanceValue)
We included different examples that hopefully will help you to identify the advantages/disadvantages from the following equivalent alternatives:
-
Either in Scala
-
Xor in Cats
Scala's wrapper for futures operations
import concurrent.Future
import concurrent.ExecutionContext.Implicits.global //default thread pool
val f: Future[String] = Future { "Hello world!" }
// when the future is done:
f.onComplete {
case Success(value) =>
println(s"this is the actual value!")
case Failure(ex) =>
println(s"Houston, we got a problem: ${ex.getMessage}")
}