Scala

Scala es un lenguaje funcional y orientado a objetos compatible con la máquina virtual de Java. Wiki En esta publicación, no pretendo hacer un curso intensivo de Scala, si no una serie de ejemplos comparados que no muestren las posibilidades de este lenguaje y de la programación funcional. Si después de leer el articulo os pica la curiosidad aquí tenéis un libro de referencia: Scala.

Pues empecemos. Para probar los siguientes ejemplos puedes emplear el siguiente editor online para Scala https://paiza.io/es/projects/new

Todo en Scala es un objeto, eso significa que los elementos del lenguaje todos tienen propiedades implícitas. Como vemos en el primer ejemplo podemos realizar operaciones matemáticas básicas empleando los operadores de toda la vida o podemos usar los operadores funcionales.

En programación clásica para sumar 2 números emplearíamos el operador suma +.

var x = 5
var tradicional = 1+(2*(3/(x)))

En programación funcional aprovechamos los operadores implícitos de Scala, que van precedidos del punto.

var funcional = 1.+(2.*(3./(x)))

A continuación, el código completo.

object Main extends App{ 
   var x = 5
   var tradicional = 1+(2*(3/(x))) 
   var funcional = 1.+(2.*(3./(x))) 
   println("Operación tradicional :( "+ tradicional) 
   println("Operación funcional :) "+ funcional) 
}

Si bien, en código tan básico no supone una ventaja radical como veremos más adelante supone una simplificación inmensa del código. Otras de las características de Scala es la asignación perezosa de tipos, es decir es el compilador el que le asigna el tipo a la variable en base a su contenido. Este tipo de variables dinámicas son : Int , Long , Float, Double, Char, String, Boolean, Null, Unit, Nothing, Any, AnyRef.

object Main extends App{ 
   var x = 5 x=x.+(3) 
   println("Variable tipo entera definida al asignar: "+ x) 

   var s="Hola holita"; 
   println("Variable tipo cadena definida al asignar: "+ s) 

   var moneda: Double = 1.3 println("Variable declarada explícitamente: "+ moneda) 
}

Estructuras Básicas de datos y operaciones

object Main extends App{ 
   //Arrays reservan el orden de entrada, tienen, duplicados y se puede modificar 
   val numbers = Array(1, 2, 3, 4, 5, 1, 2, 3, 4, 5) 
   println("Recorrido natural:") 
   numbers.foreach((i: Int) => print(" "+ i)) 
}

Recorridos natural, funcional y comprehesion con operaciones

object Main extends App{ 
   //Suma mediante recorrido 
   val numbers = Array(1, 2, 3, 4, 5, 1, 2, 3, 4, 5) 
   
   var total =0 
numbers.foreach(total += _) println("\nSuma total anónima con recorrido: "+total) var suma = numbers.reduceLeft((a:Int, b:Int) => a + b) println("Suma total con función de objeto: "+suma) println("\nSuma total por comprehesion") var acumulado=0 for (num <- numbers){ acumulado+=num; } print("\t"+acumulado) }

Filtros sobre datos

object Main extends App{ 
   //Suma mediante recorrido natural 
   val numbers = Array(1, 2, 3, 4, 5, 1, 2, 3, 4, 5) 
   println("Recorrido filtro y recorrido natural") 

   var result =numbers.filter((i: Int) => i % 2 == 0) 
   result.foreach((i: Int) => print(" "+ i)) 

   println("\nRecorrido filtro y recorrido funcional") 
   numbers.filter((i: Int) => i % 2 == 0).foreach((i: Int) => print(" "+i)) 

   println("\nRecorrido filtro y recorrido por comprehesion") 
   for (num <- numbers.filter((i: Int) => i % 2 == 0)) 
   print("\t"+num) 
}

Listas

object Main extends App{ 
   //Listas 
   // Preservan el orden, pueden contener duplicados y son inmutables 
   val numbers = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5) 

   println("Recorrido natural:") 
   numbers.foreach((i: Int) => print(" "+ i)) 

   println("\nRecorrido filtro y recorrido funcional") 
   numbers.filter((i: Int) => i % 2 == 0).foreach((i: Int) => print(" "+i)) 
}

Conjuntos sets

object Main extends App{
   //Sets
   // No preservan el orden, no pueden contener duplicados
   val numbers = Set(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
   println("Recorrido natural:")
   numbers.foreach((i: Int) => print(" "+ i))
   println("\nRecorrido filtro y recorrido funcional")
   numbers.filter((i: Int) =&gt; i % 2 == 0).foreach((i: Int) => print(" "+i))
}

Tuplas

object Main extends App{
   //Tuples Agrupar valores de diferente tipo
   val antonio = ("Antonio",37, 10)
   
   //Acceso a los campos
   println("Nombre: "+antonio._1+" Edad: "+antonio._2+" Calificación:"+antonio._3)
   def abel = ("Abel",27, 5)
   val (nombre,edad,calificacion)= abel
   println("Nombre: "+ nombre + "Edad: "+edad+"Calificación:"+calificacion)
   
   //Acceso por iterador
   antonio.productIterator.foreach{ i =>println("Campo = " + i )}

   //Conversión con funcion propia
   println("Conversión a String: " + antonio.toString())
   
   //Lista de tuplas
   val alumnos = List(("Antonio",37, 10),("Abel",27, 5))
   alumnos.foreach{ alumno => val (nombre, edad, calificacion) = alumno
                   println(nombre+" "+edad+" "+calificacion)
   }
}

Maps

import scala.collection.mutable
object Main extends App{
   // Maps permite almacenar datos clave->valor
   val alumnos = Map("Antonio" -> "37", "Abel" -> "27")
   for ((nombre,nota) <- alumnos) 
   printf("Nombre: %s, Nota: %s\n", nombre,nota)

   // crear mapa vacio
   var estudiantes = scala.collection.mutable.Map[String, String]()

   // crear mapa con valores iniciales
   var aprendices = scala.collection.mutable.Map("Antonio" ->"Excelente", "Abel" -> "Suspenso")
   println("Mapa creado e inicializado")
   for ((nombre,nota) <- alumnos) 
   printf("Nombre: %s, Nota: %s\n",nombre, nota)

   println("Agregar a Gloria y Ana")
   // agregar elementos +=
   aprendices += ("Gloria" -> "Bien")
   aprendices += ("Ana" -> "Bien", "Juan" -> "Aprobado")
   for ((nombre,nota) <- aprendices) printf("Nombre: %s, Nota: %s\n",nombre, nota)

   // quitar elementos -=
   aprendices -= "Abel"
   aprendices -= ("Ana", "Gloria")
   println("Quitar Abel, Ana y Gloria")
   for ((nombre,nota) <- aprendices) printf("Nombre: %s, Nota: %s\n", nombre, nota)

   // Actualizar elementos
   aprendices("Antonio") = "Matrícula de honor"
   println("Actualizar Antonio")
   for ((nombre,nota) <- aprendices) 
   printf("Nombre: %s, Nota: %s\n", nombre, nota)
}

Combinación de funciones

Map, Foreach, filter, zip, groupby, partition, find, drop & dropWhile, foldLeft, foldRigth, flatten, flatMap, sliding

import scala.collection.mutable
object Main extends App{
    val numbers = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
    println("Operacion y mostrar por pantalla")

    val producto=numbers.map((i: Int) => i*2)
    producto.foreach((i: Int) => print(" "+ i))

    println("\nFiltro, operacion y mostrar por pantalla")
    numbers.filter((i: Int) => i % 2 == 0).map((i: Int) =>i*2).foreach((i: Int) => print(" "+ i))
}

Zip

import scala.collection.mutable
object Main extends App{
    val numbersA = List(1, 2, 3, 4, 5)
    val lettersB = List("a", "b", "c", "d", "e")

    println("Operacion y mostrar por pantalla indexado")
    numbersA.zip(lettersB).zipWithIndex.foreach ( d=>println(s"Clave:"+d._2+" Valor: "+ d._1))

    println("Operacion y mostrar por pantalla sin indice")
    numbersA.zip(lettersB).foreach { num => val (clave,valor)= num
        println("Clave:"+clave+" Valor: "+ valor)
    }

    println("\nFiltro, operacion y mostrar por pantalla")
    numbersA.filter((i: Int) => i % 2 == 0).zip(lettersB).foreach { 
    num => val (clave,valor)= num 
    println("Clave:"+clave+" Valor: "+ valor)
    }
}

Partition

import scala.collection.mutable
object Main extends App{
    val numbers = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
    println("Operacion y mostrar por pantalla")
    
    val (a,b)=numbers.partition(_ % 2 == 0)
    
    println("Lista de pares")
    a.foreach((i: Int) => print(" "+ i))
    
    println("\nLista de impares")
    b.foreach((i: Int) => print(" "+ i))
}

Groupby

import scala.collection.mutable
object Main extends App{
    val numbers = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)

    println("Operacion y mostrar por pantalla")
    val grupos=numbers.groupBy(_ % 2 == 0)

    println("Lista de pares")
    grupos(true).foreach((i: Int) => print(" "+ i))

    println("\nLista de impares")
    grupos(false).foreach((i: Int) => print(" "+ i))
}

Find

import scala.collection.mutable
object Main extends App{
    val numbers = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)

    println("Operacion y mostrar por pantalla")
    val num=numbers.find((i: Int) => i == 5)
    println("Encontrado "+num)

    println("Encontrado "+numbers.find((i: Int) => i > 5))

}

Drop y dropWhile

import scala.collection.mutable
object Main extends App{
    val numbers = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
    println("Operacion y mostrar por pantalla")
    println(numbers.drop(5).toString)
    println(numbers.toString())
    
    println(numbers.dropWhile(_%2==0).toString)
    println(numbers.toString())
    
    println(numbers.dropWhile(_%2!=0).toString)
    println(numbers.toString())
}

FoldLeft y foldRigth

import scala.collection.mutable
object Main extends App{
    val numbers = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
    println("Operacion y mostrar por pantalla")
    println("FoldLeft")
    numbers.foldLeft(0) { 
           (m: Int, n: Int) => println("m: " + m + " n: " +n); m + n 
    }
    println(numbers.foldLeft(0)((m: Int, n: Int) => m + n))

    println("FoldRight")
    numbers.foldRight(0) { 
            (m: Int, n: Int) => println("m: " + m + " n: "+ n); m + n 
    }
    println(numbers.foldRight(0)((m: Int, n: Int) => m + n))
}

Flatten

import scala.collection.mutable
object Main extends App{
    val numbers = List(List(1, 2, 3, 4, 5) ,List(1, 2, 3, 4, 5))
    val union = numbers.flatten
    println("Operacion y mostrar por pantalla")
    union.foreach((i: Int)=> print(" "+i))

    val couples = List(List("Abel", "suspenso"), List("Antonio","sobresaliente"))
    val people = couples.flatten

    println("\n"+people.toString)
    val peopleOrder = couples.flatten.map(_.capitalize).sorted
    println("\n"+peopleOrder.toString)

    val misAmigos = List("Marina", "Andrea", "Paula")
    val abelAmigos = List("Bin Laden", "Hitler","Calamardo")
    val gloriaAmigos = List("Bob Esponja", "Paula", "Patricio")
    val amigosDeAmigos = List(abelAmigos, gloriaAmigos)
    val amigosDeAmigosFiltrados = amigosDeAmigos.flatten.distinct
    
    println("\n"+amigosDeAmigosFiltrados.toString)

}

FlatMap

import scala.collection.mutable
object Main extends App{
    val numbers = List(List(1, 2, 3, 4, 5) ,List(1, 2, 3, 4, 5))
    println(numbers.flatMap(x => x.map(_ * 2)))

    numbers.flatMap(x => x.map(_ * 2)).filter((i: Int) => i % 2 ==0).foreach((i: Int) => print(" "+ i))
}

Funciones

import scala.collection.mutable
object Main extends App{
    def addInt( a:Int, b:Int ) : Int = {
       var sum:Int = 0
        sum = a + b
        return sum
    }

    println( "Suma : " + addInt(5,7) )
}

Clases

import scala.collection.mutable
object Main extends App{
    class Alumno(nom: String, not: Int) {
        var nombre: String = nom
        var nota: Int = not
        override def toString(): String = "Alumno: " + nombre + ", " + nota + "";
    }

    val antonio = new Alumno("Antonio", 10)
    println(antonio)

    val abel = new Alumno("Abel", 1)
    println(abel)

    val gloria = new Alumno("Gloria", 7)
    val alumnos = antonio :: abel ::

    gloria :: Nil

    alumnos.foreach((a: Alumno) => println(" "+ a))

    println("Ordenados por nota ascendente: " + alumnos.sortBy(_.nota))
    println("Ordenados por nota descendente: " + alumnos.sortBy(-_.nota))

}

Bibliografía

https://paiza.io/projects
http://www.scala-lang.org/docu/files/ScalaTutorial-es_ES.pdf
https://www.tutorialspoint.com/scala/scala_data_types.htm
https://docs.scala-lang.org/es/tutorials/scala-for-java-programmers.html
http://docs.scala-lang.org/cheatsheets/index.html
https://twitter.github.io/scala_school/collections.html
http://www.codecommit.com/blog/scala/quick-explanation-of-scalas-syntax
https://alvinalexander.com/scala/scala-tuple-examples-syntax
https://alvinalexander.com/scala/create-iterating-scala-string-maps
https://alvinalexander.com/scala/iterating-scala-lists-foreach-for-comprehension
http://allaboutscala.com/tutorials/chapter-2-learning-basics-scala-programming/scalatutorial-learn-use-for-comprehension/
https://www.tutorialspoint.com/scala/scala_tuples.htm
https://www.artima.com/forums/flat.jsp?forum=283&thread=243570
https://alvinalexander.com/scala/how-to-split-sequences-subsets-groupby-partitionscala-cookbook
https://alvinalexander.com/scala/scala-for-loops-foreach-how-to-translated-by-compiler
https://alvinalexander.com/scala/examples-scala-sequences-collection-methods-seq-listarray-buffer
https://alvinalexander.com/scala/how-create-scala-list-range-fill-tabulate-constructors

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *