introduction to scala
TRANSCRIPT
Good Parts
2
JVM & JAVA INTEROPERABILITY STATICALLY TYPED
TYPE INFERENCE REPL
EXPLICIT MUTABILITY NO SEMICOLON
EVERYTHING IS AN OBJECT MIXINS
Bad Parts
3
IDE JARS & MAVEN
LEARNING GURVE COMPILE TIME
Object Oriented Programming
CLASSES OBJECTS
VISIBILITY INTERFACES
ABSTRACT CLASS INHERITANCE
Scala Variables & Values
5
val labels = Set(“")val labels = Set[String](“”)
var labels = Set[String](“”)
Mutables
Inmutables
Type Inference
Visibility
6
Public by default
Instance private to the current instanceval Num = 1private[this] val Num = 1private val Num = 1private[package] val Num = 1protected val Num = 1
Instance private to the class
Instance private to a custom package
Instance protected to its children
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] {
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
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
Functional Programming
FUNCTIONS AS FIRST CITIZENS IMMUTABILITY
CURRYING CLOSURES
LAZY EVALUATION PATTERN MATCHING
TYPE CLASS ALGEBRAIC DATATYPES
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
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
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):
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 } toOptionval futSize: Future[Int] = for { result <- readAsync() list <- result } yield list.sizeval futSizeMap: Future[Option[Int]] = readAsync().map { result: Option[List[String]] => result.map((list: List[String]) => list.size) }
Future, Option, Try, Either
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
Good Ecosystem
AKKA PLAY FRAMEWORK
SPARK SBT
SCALOID SCALAJS
ORMS TYPELEVEL
SCALAJSFINAGLE
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
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
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
Scala wants U ;)
20
https://www.coursera.org/course/progfun
http://scala-exercises.47deg.com/koans