Page 1
Capacitación TecnológicaCientífica para BoliviaCatecbol
La unión es la fuerza
facebook.com/catecbol @catecbol [email protected]
Fundamentos de Scala
University of Applied Sciences and Arts Western Switzerland, HES-SO
Jean-Paul Calbimonte
Page 2
Jean-Paul Calbimonte
Formación académica:
• Ingeniería de Sistemas: Universidad Católica Boliviana, Bolivia
• Master en Informática: École Polytechnique Fédérale de Lausanne EPFL, Suiza
• Doctorado en Inteligencia Artificial: Universidad Politécnica de Madrid, España
Experiencia:
• Investigador adjunto, University of Applied Sciences and Arts Western Switzerland
• Postdoctorado, École Polytechnique Fédérale de Lausanne EPFL, Suiza
• Software dev: pirAMide informatik, medspazio, Cochabamba
Área de Investigación:
• Procesamiento de streams, RDF streams, ingeniería ontológica, e-Health
http://jeanpi.org
Page 3
Fundamentos de Scala
¿Qué es Scala?lenguaje escalable
tipos estáticos
orientado objetos+
funcional
sintaxis concisa
corre en JVM
compatible con Java
abstracción
concurrencia, multi-hilosecosistema Scala
Page 4
Scala: ideas básicas
2. toda funcion es un valor
1. todo valor es un objeto
Scala combina ambos paradigmas
Page 6
Prueba Scala en línea ahora mismo!
http://tinsmith.herokuapp.com/
Page 7
Scala: expresiones y tipos
1 //> res0: Int(1) = 1
true //> res1: Boolean(true) = true
2+3 //> res2: Int(5) = 5
2.4+3 //> res3: Double(5.4) = 5.4
math.Pi //> res4: Double(3.141592653589793) = 3.141592653589793
math.log(1) //> res5: Double = 0.0
"cadena" //> res6: String("cadena") = cadena
"cadena" + 4 //> res7: String = cadena4
3/0 //> java.lang.ArithmeticException: / by zero
cada expresión es una función que resulta en un valor
cada valor tiene un tipo de dato, e.g. Int, String
2+3 //> res2: Int(5) = 5
Page 8
Scala: diseccionando una expresión
2+3 //> res2: Int(5) = 5
2.+(3) //> res8: Int(5) = 5
se puede escribir como:
objeto argumento
método
"34".toInt < 20 //> res9: Boolean = false
Page 9
val num=3 //> num : Int = 3
println(num) //> 3
val texto="catecbol" //> texto : String = catecbol
val num2:Int=3 //> num2 : Int = 3val mix="texto"+34+true //> mix : String = texto34true
var num3=3
num3 = 5
// no se puede reasignar un val
num2 = 5
// no se puede reasignar con otro tiponum3 = "texto"
Scala: valores y variablesse infiereel tipo
❌
declaraciónexplícita
❌
Page 10
(s:String) => "cadena" + s //> res0: String => String = <function1>
val sumarPi = (num:Int) => Pi+num //> sumarPi : Int => Double = <function1>
sumarPi(23) //> res1: Double = 26.141592653589793
val calcular=(n1:Int,n2:Double) => {
val n3=n1*n2
n3*5
} //> calcular : (Int,Double) => Double = <function2>
calcular(3,4.5) //> res2: Double = 67.5
Scala: funciones
parámetro
función anónimacuerpo de la
función
val puede ser una función
Page 11
Scala: colecciones
val arr1=Array(3,5,6,4) //> arr1 : Array[Int] = Array(3, 5, 6, 4)
val arr2=Array(Array(5,4,2)
Array(3,2,4),
Array(1,5,4))
arr1(2) //> res0: Int = 6
arr2.flatten //> res1: Array[Int] = Array(5,4,2,3,2,4,1,5,4)
val arr3=ArrayBuffer(3,2,4) //> scala.collection.mutable.ArrayBuffer[Int]
arr3+=4 //> res2: ArrayBuffer(3, 2, 4, 4)
Page 12
Scala: colecciones
val map1=Map("cbba"->"Cochabamba",
"lp" ->"La Paz",
"tri" ->"Trinidad")
map1("cbba") //> res3: String = Cochabamba
map1.getOrElse("abc", "ninguno") //> res4: String = ninguno
val bol=("bol","Bolivia")
val chi=("chi","Chile")
val arg=("arg","Argentina")
Seq(bol,chi,arg).toMap //> res5: scala.collection.immutable
.Map[String,String]
map1.asJava //> res6: java.util.Map[String,String]
Page 13
Scala: listas
List(1,3,5,6,9) //> res0: List[Int] = List(1, 3, 5, 6, 9)
Seq(3,6,8,9) //> res1: Seq[Int] = List(3, 6, 8, 9)
(1 to 6) //> res2: Range(1, 2, 3, 4, 5, 6)
(0 until 10) //> res3: Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
val lista=(1 to 5) //> lista: Range(1, 2, 3, 4, 5)
lista.filter(i => i<4) //> res4: Vector(1, 2, 3)
lista.filter(i=>i%2==0) //> res5: Vector(2, 4)
lista.map(i=>i*2) //> res6: Vector(2, 4, 6, 8, 10)
lista.sum //> res7: Int = 15
lista.foreach(i => println(s"*$i*")) //> *1*
//| *2*
//| *3*
//| *4*//| *5*
Page 14
Scala: listas
val lista2=List(3,5.6,45,"hola",34.5,"chau")
lista2.head //> res8: Any = 3
lista2.take(3) //> res9: List[Any]=List(3, 5.6, 45)
"adios" :: lista2 //> res10: List(adios, 3, 5.6, 45,
hola, 34.5, chau)
List(20,30) ::: List(40,50) //> res11: List(20, 30, 40, 50)
lista2.map {
case s:String=>"*"
case _ => "+"} //> res12: = List(+, +, +, *, +, *)
Page 15
Scala: cadenas
val s1="cadena" //> s1 : String = cadena
s1.split('a') //> res0: Array[String] = Array(c, den)
val s2=s"$s1 es un string" //> s2 : String = cadena es un string
val num=34.56 //> num : Double = 34.56
val s3=f"$s1 y un valor de $num%2.1f" //> s3 : String = cadena y un valor de 34.6
val s4="""cadena de
varias
líneas""" //> s4 : String = cadena de
//| varias
//| líneas
Page 16
Scala: cadenas
"ab,cd,ef;gh;ij".split(",|;")
//> res1: Array[String] = Array(ab, cd, ef, gh, ij)
val r="[a-z]+".r
//> r : scala.util.matching.Regex = [a-z]+
r.findFirstIn("2653abc7878") match {
case Some(patron)=>patron } //> res2: String = abc
Page 17
Scala: clases
class Banda(nombre:String,genero:String)
val kjarkas=new Banda("Kjarkas","folclore")
class Musico(val nombre:String,banda:Banda) {
def cantar(cancion:String)={
println(s"♫♫ $cancion ♫♫")
}
}
val elmer=new Musico("Elmer Hermosa",kjarkas)
elmer.cantar("bolivia") //> ♫♫ bolivia ♫♫
println(elmer.nombre) //> Elmer Hermosa
println(elmer.banda)
Page 18
Scala: clases
class Instrumento(nombre:String,esAutoctono:Boolean=false){
override def toString=
s"El instrumento: $nombre"
}
val charango=new Instrumento("charango",true)
val bajo=new Instrumento("bajo")
println(bajo) //> El instrumento: bajo
Page 19
Scala: traits
trait Artista{
val nombre:String
val edad:Int
}
class Cantante(val nombre:String, val edad:Int, val discos:Int)
extends Artista
class Actor(val nombre:String,val edad:Int,val peilculas:Int)extends Artista
val luzmila=new Cantante("Luzmila Carpio",50,30
val jenny=new Actor("Jenny Serrano",40,2)
val artistas=Seq(luzmila,jenny)
artistas.foreach(artista=>println(artista.nombre))
//> Luzmila Carpio
//| Jenny Serrano
Page 20
Scala: clases
class Cancion(val titulo:String)
trait Cantante{
def cantar(cancion:Cancion)
}
trait Compositor{
def componer(titulo:String):Cancion
}
class Cantautor extends Cantante with Compositor{
def componer(titulo:String)={
new Cancion(titulo)
}
def cantar(cancion:Cancion)=
println(s"♫♫ ${cancion.titulo} ♫♫")
}
val matilde=new Cantautor
val regreso=matilde.componer("Regreso")
matilde.cantar(regreso) //> ♫♫ Regreso ♫♫
Page 21
Scala: objetos singletonclass Departamento(val nombre:String)
object Cochabamba extends Departamento("Cochabamba")
object Beni extends Departamento("Beni")
def iniciales(dpto:Departamento)=
dpto.nombre.take(3)
iniciales(Beni) //> res0: String = Ben
object Departamento{
def apply(s:String)=new Departamento(s)
}
Departamento("Tarija")
object Geometria {
def area(radio:Int)=math.Pi*radio*radio
}
Geometria.area(4) //> res2: Double = 50.26548245743669
Page 22
Scala: clases case
case class PlatoTipico(nombre:String,departamento:String)
val majao=PlatoTipico("majadito","Santa Cruz")
val fricase=PlatoTipico("fricase","La Paz")
println(majao.departamento)
//> Santa Cruz
val majadito=PlatoTipico("majadito","Santa Cruz")
majao == majadito
//> res0: Boolean = true
val sonso=majao.copy(nombre="sonso")
println(sonso)
//> PlatoTipico(sonso,Santa Cruz)
Page 23
Scala: match case
def evaluar(nota:String)={
nota match {
case "A" => 70
case "B" => 50
case "F" => 30
case _ => 0
}
} //> evaluar: (nota: String)Int
evaluar("B") //> res0: Int = 50
evaluar("h") //> res1: Int = 0
def verificar(a:Any)=a match{
case "A" => "una letra A"
case 4 => "un int 45"
case 4.5 => "un double 4.5"
} //> verificar: (a: Any)String
verificar("A") //> res2: String = una letra A
// match error
verificar("a")
Page 24
Scala: match case
def verificar2(a:Any)=a match {
case s:String => "string"
case d:Double => "double"
case i:Int => "int"
case _ => "otro"
}
//> verificar2: (a: Any)String
Seq("ab",5,3.4,"2",List).map(verificar2)
//> res3: Seq[String] = List(string, int, double, string, otro)
Page 25
Scala: match case
trait Region{
val nombre:String
}
case class Departamento(nombre:String) extends Region
case class Provincia(nombre:String,dpto:Departamento) extends Region
case class Municipio(nombre:String,prov:Provincia) extends Region
val cocha=Departamento("Cochabamba")
val cercado=Provincia("Cercado",cocha)
val chuqui=Departamento("Chuquisaca")
val oropeza=Provincia("Oropeza",chuqui)
val sucre=Municipio("Sucre",oropeza)
val list:Seq[Region]=Seq(cocha,cercado,oropeza,sucre)
Page 26
Scala: match case
val list:Seq[Region]=Seq(cocha,cercado,oropeza,sucre)
list map {
case Departamento(nom) => s"Depto $nom"
case Provincia(nom,dpto) => s"prov $nom en ${dpto.nombre}"
case Municipio(nom,prov) => s"muni $nom en ${prov.nombre}, dpto ${prov.dpto.nombre}"
}
//> res4: Seq[String] = List(Depto Cochabamba, prov Cercado en Cochabamba, prov
//| Oropeza en Chuquisaca, muni Sucre en Oropeza, dpto Chuquisaca)
list map {
case d:Departamento => s"Depto ${d.nombre}"
case p:Provincia => s"prov ${p.nombre} en ${p.dpto.nombre}"
case m:Municipio => s"muni ${m.nombre} en ${m.prov.nombre}, dpto ${m.prov.dpto.nombre}"
}
//> res5: Seq[String] = List(Depto Cochabamba, prov Cercado en Cochabamba, prov
//| Oropeza en Chuquisaca, muni Sucre en Oropeza, dpto Chuquisaca)
Page 27
Scala: opciones
val equipos=Map("lp"->"The Strongest",
"scz"->"Oriente",
"cocha"->"Wilster",
"oru"->"San Jose")
def obtenerEquipo(dpto:String):Option[String]={
equipos.get(dpto)
}
def hayEquipo(dpto:String)=equipos.get(dpto) match {
case Some(eq) => println(s"el equipo es $eq")
case None => println("no hay equipo")
}
hayEquipo("scz") //> el equipo es Oriente
hayEquipo("abc") //> no hay equipo
Page 28
Scala: opciones
case class Persona(nombre:String,email:Option[String])
Persona("felix",Some("[email protected] "))
Persona("lucas",None)
Page 29
Scala: excepciones
def dividir(a:Int,b:Int):Option[Double]=
try {
Some(a/b)
}
catch {
case ex:Exception=>
ex.printStackTrace
None
}
//> dividir: (a: Int, b: Int)Option[Double]
val div=dividir(3,0) //> java.lang.ArithmeticException: / by zero
Page 30
Scala: excepciones
def dividir2(a:Int,b:Int):Try[Double]=
Try(a/b)
val div2=dividir2(3,0)
//> div2 : scala.util.Try[Double] = Failure(java.lang.ArithmeticException:
div2.isSuccess
//> res0: Boolean = false
div2 match {
case Success(d)=>println(d)
case Failure(ex)=>ex.printStackTrace
}
//> java.lang.ArithmeticException: / by zero
div2.toOption
//> res1: Option[Double] = None
Page 31
Scala: implícitosclass PlatoTipico{
val ingredientes=new ArrayBuffer[Ingrediente]
}
case class Ingrediente(i:String)
def aumentar(ing:Ingrediente)(implicit plato:PlatoTipico)={
plato.ingredientes+=ing
}
implicit val silpancho=new PlatoTipico
aumentar(Ingrediente("huevo"))
aumentar(Ingrediente("arroz"))
println(silpancho.ingredientes) //> ArrayBuffer(Ingrediente(huevo), Ingrediente(arroz))
implicit def strToIngrediente(s:String)=Ingrediente(s)
aumentar("apanado")
Page 32
Scala: implícitos
implicit class StringPlus(s:String){
def quitarEspacios=s.replaceAll(" ","")
def codificar=Base64.encode(s.getBytes)
}
"la unión es la fuerza".quitarEspacios
//> res3: String = launióneslafuerza
"catecbol".codificar
//> res4: Array[Byte] = Array(89, 50, 70, 48, 90, 87, 78, 105, 98, 50, 119, 61)
Page 33
Scala: futuros
def operacionLarga={
Thread.sleep(5000)
println("terminó larga")
4
}
def operacionCorta={
Thread.sleep(1)
println("terminó corta")
}
operacionLarga //> terminó larga
//| res0: Int = 4operacionCorta //> terminó corta
Page 34
Scala: futuros
val fut=Future(operacionLarga)
operacionCorta //> terminó corta
fut.onComplete { result => println(result) }
Future(operacionLarga)
Future(operacionLarga)
Future(operacionLarga)
Thread.sleep(10000)
//| Success(4)
//| terminó larga
//| terminó larga//| terminó larga-
Page 35
Scala: java interop
import org.joda.time.DateTime
import collection.JavaConversions._
"esta cadena".getClass //> res0: Class[?0] = class java.lang.String
val fecha=DateTime.now //> fecha:org.joda.time.DateTime=2017-05-26T21:44:14.778+02:00
fecha.toTimeOfDay() //> res1: org.joda.time.TimeOfDay = T21:44:14.778
val javaLista=new java.util.ArrayList[String]
javaLista.add("a")
javaLista.add("b")
javaLista.add("c")
javaLista.foreach(println) //> a
//| b
//| c
javaLista.map(_.toUpperCase) //> res5: ArrayBuffer(A, B, C)
Page 36
Scala: scalatest
class DemoTest extends FlatSpec with Matchers {
"Una cadena " should "cumplir" in{
val s="cadena"
s should not be (null)
s.length shouldBe (6)
s should startWith ("c")
s should contain ('d')
}}
Page 37
Scala: sbt simple build tool
name := "scala-fundamentos"
organization := "jpcik"
version := "0.0.1"
scalaVersion := "2.11.8"
libraryDependencies ++= Seq(
"com.typesafe" % "config" % "1.3.1",
"joda-time" % "joda-time" % "2.9.9",
"org.scalatest" %% "scalatest" % "2.2.1" % "test",
"junit" % "junit" % "4.12" % "test"
)
resolvers ++= Seq(
"typesafe" at "http://repo.typesafe.com/typesafe/releases/",
Resolver.sonatypeRepo("public"))
http://www.scala-sbt.org/
Page 38
Scala: IDEs: Eclipse, IntelliJ
http://scala-ide.org/
Page 39
Scala: akka http://akka.io/
Page 40
Scala: play framework https://playframework.com/
Page 41
Scala: Apache Spark https://spark.apache.org
Page 42
Scala: Docs http://docs.scala-lang.org/
Page 43
Material disponible
https://github.com/jpcik/tutorials
Page 44
Capacitación TecnológicaCientífica para BoliviaCatecbol
La unión es la fuerza
facebook.com/catecbol @catecbol [email protected]
Capacitación TecnológicaCientífica para Bolivia
La unión es la fuerza
Gracias
[email protected]
Jean-Paul Calbimonte
facebook.com/catecbol [email protected]