¿Por qué Scala?

¿Qué es Scala?

Scala es un lenguaje open source creado por Martin Odersky, por concepto es un lenguaje multi-paradigma de propósito general, que combina programación orientada a objetos y funcional en un lenguaje de alto nivel y con tipos seguros. Gracias a sus tipos estáticos ayuda evitar errores en aplicaciones muy complejas. Es ejecutado en la JVM, además se integra con JavaScript, permite construir sistemas de alto rendimiento y con fácil acceso a enormes ecosistemas de librerías.

En el mundo del desarrollo de software actual es considerado como un lenguaje complejo para aprender y suelen decir que pocos desarrolladores saben cómo trabajar (de verdad) con Scala; Algo con lo que no coincido … ¿Porque miremos porque surge? Scala surge con el objetivo de ser un mejor lenguaje, cambiando esos aspectos de Java que consideramos antiguos, tediosos y frustrantes, para así tener un resultado más limpio, organizado, fácil de utilizar y con una mejor productividad final.

Scala es un acrónimo de lenguaje escalable, favorece la creación de abstracciones, la programación distribuida o simultánea, permite inmutabilidad y por ello es fácil escribir código mediante el uso de
información inmutable, incluye: first-class vals, case classes, higher order functions, higher-kinded types, typeclasses, through implicits, que hace mucho más fácil trabajar con tipos containers como Futures o Tasks.

¿Cómo puedo aprender Scala?

Hay una amplia gama de documentación para aprender Scala en la red, muchos libros buenísimos e innumerables blogs (Al final recomendamos), pero una opción que siempre recomiendo mucho, para principiantes y de la cual aprendí un montón es Scala Exercises una plataforma interactiva y práctica donde primero te explican el funcionamiento y posteriormente debe realizar un ejercicio acorde. Además tenemos siempre de forma gratuita u opcional pago para la certificación unos excelentes cursos en Coursera donde podemos aprender del pi al pa como decimos los cubanos.

Veamos un Hola Mundo y parte de su sintaxis

Como vamos a presentar un lenguaje si no explicamos su sintaxis y hacemos el típico Hola Mundo. Si comparamos con otros lenguajes como Java o JavaScript, Scala tiene una sintaxis muy similar pero con la particularidad que no es obligatorio ni el ";" al final de cada línea ni la palabra reservada return para retornar el valor de un método, cuenta con inferencia de tipos, todo es un objeto, incluyendo las funciones, bueno todo todo.

Veamos el Hola Mundo y otros ejemplos:

object HelloWorld {

  /**
    * Como insertamos un comentario en un inicio de un método y que se incluye en el ScalaDoc
    *
    * @param args describimos la entrada de argumentos o otro input value
    */
  def main(args: Array[String]): Unit = {
    //Comentario interno y creación de una variable o valiable
    //como algunos le llamamos a los val inmutables
    val message = "¡Hola, mundo!"
    println(message) //¡Hola, mundo!
  }
}

También podemos tener una versión del Hola Mundo reducida, extendemos de un trait App que facilita poder escribir y ejecutar cualquier sentencia de código:

object HelloWorldMini extends App {
  println("¡Hola, mundo!") //¡Hola, mundo!
}

Variables: En Scala las variables pueden ser mutables o inmutables solo difieren en la palabra reservada var o val ya apreciamos arriba un ejemplo inmutable veamos una mutable:

object HelloWorldVar extends App {
  // Declaramos una variable mutable vacía de tipo String
  var value: String = ""
  // Le asignamos un valor
  value = "mundo"
  // Imprimimos el valor y acá podemos ver como usar string interpolation
  println(s"¡Hola, $value!") //¡Hola, mundo!
}

Condicionales: La sentencia if … else es similar a los otros lenguajes con la particularidad que no permite ternarias

object HelloWorldIfElse extends App {
  // Podemos ver como vimos antes que si no ponemos tipo scala lo infiere por nosotros
  val language = "en"

  // podemos notar que si no tiene parámetros la función no necesita paréntesis
  def message = {
    if (language == "es") "¡Hola, mundo!"
    else if (language == "pt") "¡Olá, mundo!"
    else "Hello, world!"
  }

  println(message) //Hello, world!
}

Este mismo ejemplo lo podemos imprimir usando pattern matching, viene siendo como el equivalente al switch…case de java.

object HelloWorldPatternMatching extends App {
  val language = "pt"

  //no hay necesidad de colocar break el rompe donde primero encuentra
  val message = language match {
    case "es" => "¡Hola, mundo!"
    case "pt" => "¡Olá, mundo!"
    case _    => "Hello, world!"
  }
  println(message) //¡Olá, mundo!
}

Bucles o ciclos: Los ciclos se comportan igual como otros lenguajes con la particularidad que se les puede incluir filtros o condicionales internas, hay ejemplos como el for…yield que son muy interesantes por la particularidad y legibilidad que aporta para el trabajo con collections y monads

object Numbers extends App {
  // Podemos inicializamos una lista y al mismo tiempo le pre-populamos valores
  val numbers = List(1,2,3,4,5)

  // Recorremos la lista de números y filtramos los pares
  def pairNumbers: List[Int] = for {
    number <- numbers
    if number % 2 == 0
  } yield number

  // Imprimimos el resultado separados por ", "
  println(pairNumbers.mkString(", ")) // 2, 4

  //Plus: Ejemplo similar usando filter para los impares
  println(numbers.filter(_ % 2 != 0).mkString(", ")) // 1, 3, 5
}

Funciones: Con las funciones lo mismo solo cambia palabra reservada def, aunque al ser un lenguaje funcional permite pasar otra funciones como parámetros, además de Currying, el uso de los implicitos, o crear funciones como variable, pero eso da para otro post. No obstante presentamos algunos ejemplos sencillos:

object Functions extends App {
 //Existen dos formas de declarar las funciones

  // Una función básica y conocida acá como callByValue
  def sum(x: Int, y: Int) = x + y
  // Como la invocamos
  sum(1,2) // 3

  // Otra conocida acá como callByName donde pasamos otra función
  def product(x: => Int, y: => Int) = x * y
  // Como la invocamos
  def two() = 2
  product(two(), 6) // 12

  // U otro un poco más avanzado donde pasamos una función a ejecutar
  // Y además notemos que podemos poner parámetros por default
  def productF(f: Int => Int, x: Int, y: Int = 2) = f(x * y)
  // Como la invocamos
  // Definimos una función val
  val sum5: Int => Int = x => x + 5 // ó simplemente _ + 5
  // Pasamos la misma por parametros
  productF(sum5, 6, 6) // (6 * 6) + 5 = 41
  // Invocamos sin el ultimo valor para que tome 2 po default
  productF(sum5, 5) // (5 * 2) + 5 = 15


  // Podemos pasar como en otros lenguajes un array de parámetros
  def sumAll(x: Int, y: Int, others: Int*) = {
     x + y + others.sum
  }
  // Como la invocamos
  sumAll(1,2,3,4,5,6,7,8,9) // 45


  // O podemos implementar el método product con un ejemplo de forma recursiva
  def productRecursive(numbers: List[Int]): Int = numbers match {
       case Nil => 1 // Si la lista es vacía retornamos 1
       case x :: tail => x * productRecursive(tail) // Sino multiplicamos
   }
  productRecursive(List(1,2,3,4,5)) // 120

  //Cerramos con un ejemplo de currying
  def sumCurrying(x: Int)(y: Int): Int = x + y
  // Como la invocamos
  sumCurrying(1)(2) // 3
  // Pero podemos entonces almacenar una suma parcial en una variable
  val sum2 = sumCurrying(2) _
  // y luego invocarla con ese adelanto
  sum2(3) // 5


  //O que el segundo parámetro se inplicito de un contexto particular
  def productCurrying(x: Int)(implicit y: Int): Int = x * y
  // Definimos el implicito
  implicit val number3: Int = 3
  // Ahora consumimos con un solo parámetro y el otro lo encontrará y usará number3
  productCurrying(5) // 15
}

Además scala posee clases que se le puede crear instancias para tipico uso de POO, cuenta con case class que son clases inmutales las cuales exportan sus parámetros constructores, implementan por default el .equals y .toString, permiten usar el muy útil metodo copy y mucho más … pero dejemos espacio para otros posts.

Usos Destacados Actuales

En los últimos años viene experimentado un crecimiento espectacular y ha pasado a convertirse en un estándar para muchas empresas, startups y universidades de todo el mundo.

Además no solo utilizan Scala para crear sus nuevos proyectos, sino también para otras herramientas de gran impacto en el mercado como los Frameworks:

  • Play Framework -> Un framework de alta velocidad para el desarrollo con Java y Scala.
  • Apache Spark -> Motor de análisis para el procesamiento de datos a gran escala.
  • Akka -> Framework para aplicaciones reactivas, concurrentes y distribuidas con mayor facilidad.
  • Apache Kafka -> Herramienta para construir canalizaciones de datos y aplicaciones de transmisión en tiempo real.

… O grandes librerías que promueven y hacen que sea más fácil la programación funcional, por mencionar algunas:

  • Cats -> Librería ligera, modular y extensible para programación funcional.
  • Scalaz -> Conjunto de estructuras puramente funcionales para complementar las de Scala.
  • Magnolia -> Una Macro genérica para la materialización automática de clases de tipos para tipos de datos compuestos.
  • ZIO -> Este último creando un amplio y potente ecosistema que va a hacer en mi opinión más interesante Scala en el futuro.

¡Además de muchísimos más proyectos open source para acceso a datos, comunicación entre APIs, que favorece con creces que los nuevos y actuales seguidores vean aún más, la potencia de este hermoso lenguaje y confirmen lo interesante que es!

Que libros se recomiendan para empezar:

scala 

Ver también