5. Scala Variables & Values
5
val labels = Set(“")
val labels = Set[String](“”)
var labels = Set[String](“”)
Mutables
Inmutables
Type Inference
6. Visibility
6
Public by default
Instance private to the current instanceval Num = 1
private[this] val Num = 1
private val Num = 1
private[package] val Num = 1
protected val Num = 1
Instance private to the class
Instance private to a custom package
Instance protected to its children
7. Classes
7
Case class -> get, set, constructor auto
Traits -> Interfaces + Mixins
Generic clases/traits
Singleton Object
case class SocialNetwork(id: String, name: String)
trait LinkedList[+A] {
def isEmpty: Boolean
def head: A
def tail: LinkedList[A]
def at(index: Int): A
def prepend[B >: A](elem: B): LinkedList[B] =
new Cons(elem, this)
}
object Nil extends LinkedList[Nothing] {
class Cons[A](val head: A, val tail: LinkedList[A]) extends LinkedList[A] {
8. Mixins
8
Typesafe
Multiple inheritance
trait NeoTest
extends FunSpec
with MustMatchers
with BeforeAndAfterAll
with BeforeAndAfterEach {
}
trait HelperTest {
this: NeoTest =>
}
class NodeSpec extends NeoTest with HelperTest {
}
Used for composition
9. Abstract class
9
Java compatibilityabstract class Rel[A, B] {
val from: A
val to: B
}
case class MyRel(from: MyUser, to: MyUser,
enabled: Boolean) extends Rel[MyUser, MyUser]
Can not be instantiated
Can have a constructor
Relation is-a
10. Functional Programming
FUNCTIONS AS FIRST CITIZENS IMMUTABILITY
CURRYING CLOSURES
LAZY EVALUATION PATTERN MATCHING
TYPE CLASS ALGEBRAIC DATATYPES
11. Scala Functions
11
Every function must have a return type
Functions as parameters
You can return functions
Vector.fill(queens.length)("* “)
.updated(col, "X ").mkString
def lambda = (x: Int) => x + 1
val multiplier = (i:Int) => i * 10
def sumComp(a: Int): (Int) => Int = {
def sum(b: Int) = a + b
}
val fun = sumComp(5)
fun(1)
def sumComp(a: Int)(b: Int): Int = {
a + b
}
Currying
12. Pattern Matching
12
Like a super switchval secondElement = List(1,2,3) match {
case x :: y :: xs => y
case _ => 0
}
val foodItem = "porridge"
def goldilocks(expr: Any) = expr match {
case (`foodItem`, _) => "eating"
case ("chair", "Mama") => "sitting"
case ("bed", "Baby") => "sleeping"
case _ => "what?"
}
goldilocks(("porridge", "Papa"))
Compare & extract
13. Implicits
13
Inject parameters to a method
Automatic conversation
implicit def implChange(str:String):Int =
new Integer(str)
def sum(a:Int, b:Int):Int = a +b
sum("1", 2)
def save[T](t: T)(implicit connection: Neo4jREST,
ec: ExecutionContext):
14. Monads
14
map, flatMap, filter
for comprehension
def readAsync(): Future[Option[List[String]]] =
Future { readFile() }
def readFile(): Option[List[String]] =
Try { Source.fromURL("/tmp/file.txt").getLines().toList
} toOption
val futSize: Future[Int] =
for {
result <- readAsync()
list <- result
} yield list.size
val futSizeMap: Future[Option[Int]] =
readAsync().map { result: Option[List[String]] =>
result.map((list: List[String]) => list.size)
}
Future, Option, Try, Either
15. Type Class
Pattern
15
AKA context bound
implicit val myUserMapper = Mapper.build[MyUser]
abstract class NeoNode[T: Mapper] extends Labelable {
val MapperT = implicitly[Mapper[T]]
def save(t: T)(implicit connection: Neo4jREST, ec: ExecutionContext):
Future[Boolean] = Future {}
object ToOps{
implicit def operations(t: T) = NeoNodeOperations(t)
}
case class NeoNodeOperations(t: T) {
def save()(implicit connection: Neo4jREST, ec: ExecutionContext) =
NeoNode.this.save(t)
}
}
case class MyUser(id: String, name: String, age: Int)
implicit val userNode = NeoNode("user", (user: MyUser) => user.id)
import graph.model.orm.UserNodes.userNode.ToOps._
val node1 = MyUser("1", "Michel Perez", 27)
node1.save()
Mix traits - abstract class
& implicit
17. Actors
17
Lightweight threads
Event oriented
class BloodRequester extends Actor {
implicit val executor = context.dispatcher
override def receive: Receive = {
case BloodRequest(request) =>
DonorDAO.findNear(request).map { donors =>
donors.foreach { donor =>
facebookNotifier ! FacebookNotify(donor, request)
}
}
}
}
Restart in failures
Supervision
18. ScalaTest
18
Test Unit
trait NeoTest
extends FunSpec
with MustMatchers
with BeforeAndAfterAll
with BeforeAndAfterEach {
override def beforeEach(): Unit = {
NeoDBCleaner.cleanDB()
}
describe("UserDAOs") {
it("creates an user an checks the default group") {
withUser { (user, saved) =>
saved must be(true)
val query = s"""match (a:user {id: "${user.id.getOrElse("")}"})-[c:has_group]-
>(b:group) return a, b, c"""
val result = Await.result(NeoQuery.executeQuery[UserLogin, Group, HasGroupLogin]
(query), 2 seconds)
result.length must be(1)
}
}
}
Multiple Paradigms
TDD
BDD
19. ScalaZ
19
Inspired in Haskell
case class Box[A](itemType: A)
implicit val machFunctor = new Functor[Box] {
override def map[A, B](fa: Box[A])(f: (A) => B): Box[B] = {
val b = f(fa.itemType)
Box(b)
}
}
import machFunctor.functorSyntax._
val boxInt = Box(1)
val boxString = boxInt map { x => s"$x..." }
More functional
20. Scala wants U ;)
20
https://www.coursera.org/course/progfun
http://scala-exercises.47deg.com/koans