[Scala] Hilo General - Solo personas funcionales y distribuidas

B

Qué es Scala?

Scala es un lenguaje de programación multi-paradigma diseñado para expresar patrones comunes de programación en forma concisa, elegante y con tipos seguros. Integra sutilmente características de lenguajes funcionales y orientados a objetos. La implementación actual se ejecuta en la máquina virtual de Java y es compatible con las aplicaciones Java existentes.

Scala fue creado por Martin Odersky.

Características

Orientación a objetos

Scala es un lenguaje de programación puro orientado a objetos, en el sentido de que cada valor es un objeto. El tipo y comportamiento de los objetos se describe por medio de clases y traits. La abstracción de clases se realiza extendiendo otras clases y usando un mecanismo de composición basado en mixins como un reemplazo limpio de la herencia múltiple.

Lenguaje funcional

Scala también posee características propias de los lenguajes funcionales. En Scala las funciones son valores de primera clase, soportando funciones anónimas, orden superior, funciones anidadas y currificación. Scala viene integrado de fábrica con la técnica de pattern matching para modelar tipos algebraicos usados en muchos lenguajes funcionales.

Tipificado estático

Scala está equipado con un sistema de tipos expresivo que refuerza a que las abstracciones de tipos se usen en forma coherente y segura.

Extensibilidad

Scala se diseñó teniendo en mente el hecho de que en la práctica el desarrollo de aplicaciones requiere a menudo de extensiones específicas del lenguaje. Para ello, Scala proporciona una combinación única de mecanismos que hacen fácil y sin problemas agregar construcciones nuevas al lenguaje en forma de bibliotecas.

Inmutabilidad

Como lenguaje funcional, una de sus principales características es la inmutabilidad, Scala se asienta sobre muchos conceptos matemáticos que requieren de la inmutabilidad para seguir siendo válidos.

¿Cómo empiezo?

Lo más común es usar Intellij IDEA de Jetbrains con el plugin de Scala.

En mi caso prefiero usar VS Code porque es lo que uso en mi día a día y ya lo tengo tuneado con el plugin de VIM, atajos de teclado etc, así que estoy usando VS Code + Metals. Me ha soprendido lo bien que funciona, además, VS Code es más ligero que Intellij Idea.

Tanto Metals como Intellij permiten crear unos archivos llamados "worksheets" que vienen a ser como los "playgrounds" de Swift.

Una worksheet es un archivo scala con extensión .sc que puede ejecutar y obtener los resultados de la evaluación en una vista especial que aparece en el editor.

¿Para qué se usa?

Es común verlo en entornos de procesamiento de big data, se suele usar junto con Spark, Kafka y Akka. Estas herramientas, además de ser proyectos con gran impacto en el mercado, fueron construidas intencionadamente en Scala.

Decir también que la curva de aprendizaje de este lenguaje para los que venimos de otros no funcionales es bastante grande, aún así os animo a probar, yo estaba muy ciego con Python hasta que he empezado a hacer cosillas con Scala.

No soy ningún experto en Scala, pero encantado de ayudar y recibir ayuda.

Buen foro

4
PiPePiTo

En el curro lo estamos usando para hacer tests con Gatling y la relación amor/odio que estoy teniendo está siendo intensa.

Pero una vez le coges el truco y aprender la diferencia entre val y var... La cosa ya avanza xD

1 1 respuesta
B
#2PiPePiTo:

la relación amor/odio que estoy teniendo está siendo intensa

jajajajaj te entiendo bien.

Yo lo que peor llevo sin duda alguna son la HOF y la recursividad compleja

MTX_Anubis

Obligatorio:

https://www.mediavida.com/foro/dev/programacion-funcional-scala-clojure-etc-446872

1 respuesta
B

#4 sabía que existía, pero lleva tiempo muerto y no es específico de Scala, me he leído las normas antes y ponía que antes de reflotar algo viejo, casi mejor crear uno nuevo, así que siendo este específico de Scala, me he tirado a la piscina

Phatality

Lo uso en el dia a dia con un framework llamado Scio (apache beam) para big data jobs. Demasiada magia y complejidad innecesaria a veces.

1
1 mes después
B

Dejo por aquí un ejemplo de .gitignore para proyectos de Scala.

Hay un apartado por cada ide que uséis Eclipse, VSCode, Intellij IDEA etc

https://alvinalexander.com/source-code/scala/sample-gitignore-file-scala-sbt-intellij-eclipse/

kirk01

¿Recomendáis Scala para alguien que está empezando a programar? Me da la impresión de que este lenguaje está más orientado a gente con experiencia que vienen de otros lenguajes como Java, C#, etc.

¿Sería muy difícil encontrar trabajo de Scala sin experiencia previa? como junior, vamos.

Llevo varios días mirando la documentación y el handbook y de momento me parece la mejor que he visto, además de que me ha gustado bastante la sintaxis del lenguaje.

2 respuestas
B

#8 Si estás empezando a programar no te recomiendo Scala, tiene una curva de aprendizaje muy alta.

Sobre el curro, a mí me han ofrecido siendo junior en Scala, pero ya llevo 10 años picando en otro lenguaje.

Yo cuanto más pico scala, menos me gustan el resto de cosas

1 1 respuesta
kirk01

#9 Gracias, lo suponía.. bueno, igualmente intentaré seguir aprendiendo Scala y ver si puedo ampliar mis conocimientos de OOP con este lenguaje. Llevo unos meses con Java y ya le he cogido una tirria tremenda.

1
desu

#8 leete el redbook

es un gran libro para aprender a programar

da igual que no tengas experiencia

tansolo saltate la OOP y centrate en tener cosas funcionales peque;as

el unico problema de scala que encontraras es la complejidad, muchas keywords y patrones para hacer cosas que realmente son muy faciles y simples pero en el lenguaje no estan tan bien integradas como otros funcionales.

tansolo es eso, complejidad.

pero a nivel individual te aportara lo mismo que cualquier otro lenguaje del palo.

yo no te lo recomiendo si crees que la complejidad te supondra demasiado esfuerzo. pero prueba los primeros capitulos.

1 2 respuestas
kirk01

#11 pues tiene muy buena pinta el libro, además que en la web dice que está enfocado para gente que no tiene ni idea de FP

justamente estaba pensando en pillarme este otro de manning... https://www.manning.com/books/get-programming-with-scala, pero parece que el redbook es mejor para noobs como yo

gracias!

2 respuestas
B

#12 yo tengo el redbook que también me lo recomendó #11 y es una pasada, hay muchos ejemplos y ejercicios que debes resolver, los tienen todos hechos aquí por si te atascas en alguno:

https://www.scala-exercises.org/fp_in_scala/getting_started_with_functional_programming

1
B

#12 y otra cosa, por reddit y más sitios en general oirás mucho hablar de usar VSCode + Metals como entorno de desarrollo para Scala. Olvídate, le queda muchísimo a esto todavía. Yo lo estuve probando un tiempo porque en el curro uso VSCode y estoy más acostumbrado pero para Scala es basura.

Intellij IDEA sin dudarlo

2
desu

Si y el problema es la complejidad en si del lenguaje, no de las ideas, i.e:

def isSorted[A](as: Array[A], ordering: (A, A) => Boolean): Boolean = {
  @annotation.tailrec
  def go(n: Int): Boolean =
    if (n >= as.length - 1) true
    else if (!ordering(as(n), as(n + 1))) false
    else go(n + 1)
  go(0)
}

en otro lang com haskell seria algo asi:

  • isSorted acepta una lista de A y devuelve bool
  • donde A es un generico que implementa Ord (para tener orden)
  • lista vacia y 1 elemento siempre True
  • 2 elementos pues los comparas
  • 2 elementos y una lista, comparas los elementos y el resto recursivo... fin
isSorted :: Ord a => [a] -> Bool
isSorted []  = true
isSorted oneElement = true
isSorted (head : tail) = head > tail
isSorted (first : second : xs)  = first > second and isSorted (second ++ xs) 

Todo se compone mas facil, tiene sintaxis mas entendible (si no haces el bobo).

En scala para algo tan facil fijate todo lo que necesita.

Si quieres tener la misma firma que en scala pero en haskell, pasandole el predicado de ordering como parametro podrias hacer:

isSorted :: Ord a => [a] -> Predicate -> Bool
isSorted [] _   = true
isSorted oneElement _  = true
isSorted (head : tail) p   = p head tail
isSorted (first : second : xs) p  = (p first second) and (isSorted (second ++ xs) p)

Pongo parentesis para que te sea mas entendible.

Pues bueno como haskell tienes otros diez lenguajes funcionales que en 4 lineas haras lo que scala hace en 20.

Para que necesitas esa anotacion de tail rec? que es eso de go? que es esa sintaxis tan verbosa? Scala estaria mejor si fuese asi y funcionase igual que arriba:

def isSorted(as: Array[A], ordering: (A, A) => Boolean): Boolean = {
    if (as.length <= 2) true
    else if (!ordering(first(as), second(as))) false
    else isSorted(second(as), tail(as), ordering)
}

Disclaimer; hace a;os que no toco haskell y no esta perfecto, pero pa que se entienda.

1 1 respuesta
kirk01

#15 el código de Scala lo he entendido bien en su gran mayoría, pero con el de Haskell me he perdido salvo por 2 o 3 cosas, algo normal supongo porque no estoy acostumbrado a lenguajes FP puros

pero ya veo lo que quieres mostrarme, y que la sintaxis de haskell queda más "limpia"

1 respuesta
desu

#16 Te lo hago en typescript si quieres, he hecho haskell porque he dicho ostia hace tiempo que no hago

function isSorted<Type>(list: Type[]): boolean {
    return (list.length == 0 || list.length == 1) ? true
        : (list.length == 2) ? list[0] < list[1]
        : list[0] < list[1] && isSorted(list.slice(1))
}

Lo importante es que veas que el patron es el mismo... da igual el lenguaje, solo cambia sintaxis

En scala tienes el @tailrec y el go por detalles de implementacion, eso te da igual cuando aprendes

Lo mejor para aprender si no te da miedo la sintaxis es meterte con Scheme o Racket. Te lo dejo en Racket:

(define (is-sorted xs)
  (cond
    [(<= (length xs) 1) true]
    [(= (length xs) 2) (< (first xs) (second xs))]
    [else (and 
        (< (first xs) (second xs)) 
        (is-sorted (list-tail xs 1)))]))

Que aqui cuesta solo entender la notacion y no liarte con los parentesis, pero en unos dias practicandolo ni te enteras y es el lang mas facil de entender XD

Como puedes ver 4 lang funcionales, siempre igual... cambia sintaxis. lo que tienes que aprender es la idea y ganar un poco de soltura.

1
17 días después
B

A raíz de mi nuevo empleo, me han salido muchos haters diciendo que Spark está deprecated, que ahora se usa Dask + Python, pero en mi jornada de estudio de hoy, he estado viendo los Datasets, que se incluyeron en Spark 3. Éstos son una evolución de los dataframes, pero sorpresa!! la api de Datasets no está disponible en Python, solo en Scala y Java, por el tema de las case class de Scala.

Como moraleja, no influirme por opiniones de otros, menos todavía si son fanboys de python

1
B

Microsoft presenta SynapseML: A simple, multilingual, and massively parallel machine learning library.

SynapseML es una biblioteca de código abierto creada para simplificar la creación de pipelines de machine learning escalables y distribuidas. Puede usarse con varios lenguajes de programación: Python, R, Sacala y Java.

Con SynapseML, los desarrolladores pueden construir sistemas escalables e inteligentes para resolver diferentes problemas, entre los que destaco:

  • Anomaly detection
  • Computer vision
  • Deep learning
  • Gradient boosting
  • NLP

+Info

En cuanto me asiente un poco en el trabajo nuevo me gustaría probar la herramienta

6 meses después
B

Dejo por aquí una lista de reproducción de un side project desde 0 haciendo un docker client en Scala

El tipo en cuestión trabaja en Disney Streaming, se llama Jakub Kozłowski y tiene un toque flipante en Scala

1
10 meses después
B

@desu he leído este artículo
https://scalajobs.com/blog/functional-data-modeling-in-scala/

Habla de otra forma de representar el dominio usando "algebraic data types". ¿Qué opinas? ¿Crees que realmente resuelve algún problema?

1 respuesta
desu

#21 No entiendo la pregunta.

De el blog:

It is pity that the majority of mainstream programming languages realised only later that it is “a must” for a programming language to have dedicated features for dealing with data.

A set of new features which we are currently observing in mainstream programming languages (data classes, records and so on) is a proliferation of such a necessity.

  • Esto esta mal, es ridiculo y es mentira. En C de toda la vida tienes unions y enums...
    Data classes, records and "so on", es algo de scala, java, kotlin... asi que esos mainstream languages que tan malos son basicamente se refiere a "java".

  • "ADT" no es mas que una fancy word de programacion funcional y mates para referirnos a uniones y sumas de tipos...

  • Y luego lo de "smart constructors" es otra bobada que les gusta a los programacion funcional para parecer distintos y mas inteligentes que el resto, un constructor de toda la vida y devolver el error de alguna manera (mediante un option, either, tupla de error). Que la gente no sepa ni escribir un constructor dice mucho de el nivel de los programadores, y que otros se inventen "fancy words" para sonar inteligentes dice mucho de los "otros programadores" prepotentes e imbeciles que hay en el mundo de Scala y la FP.

Asi que no entiendo muy bien la pregunta, cuando necesitas una union la usas, si necesitas tener enums o algo para hacer un pattern matching exhaustive lo usas... algunos lenguajes el compilador te lo verificara y con otros lo puedes hacer tu mismo...

Todo tiene su caso de uso y sus pros y cons. Y en el caso de Scala y la JVM imagino que esto a parte de escribir diez mil lineas de codigo y sobre-enginieria "sintactica" para tener algo tan basico tambien tendra sobre costes por ser objetos en memoria y sera mucha syntax sugar y analisis en tiempos de compilacion. Que te daran igual porque estas usando Scala en primer lugar.

1 respuesta
B
#22desu:

Y luego lo de "smart constructors" es otra bobada que les gusta a los programacion funcional para parecer distintos

A mí los smart constructors me gustan, haces la clase privada para que no se pueda instanciar directamente y pones unas restricciones para asegurarte que el objeto que creas tiene sentido.

Lo que no me queda claro es el uso de ADT, me parece que puedes evitar errores, pero también un poco oversized, ¿qué opinas de esto? ¿recomiendas usar ADTs?

1 respuesta
desu
#23vago_21:

haces la clase privada para que no se pueda instanciar directamente y pones unas restricciones para asegurarte que el objeto que creas tiene sentido

Estas haciendo cosas para que los inutiles de tus compañeros no la lien? no se primer problema.

Segundo problema es que tu lenguaje tiene un constructor por defecto que en lugar de devolver un error (option, either, tupla error) te devuelve siempre un success y eso puede tirar una excepcion. Lenguaje de mierda? segundo problema.

Ese patron de diseño "smart constructor" existe porque tu lenguaje esta mal diseñado. Como he dicho mil veces y decia Peter Norvig en su paper de 1995, todos los patrones de diseño sirven para cubrir CARENCIAS del lenguaje. No son "buenas practicas" de nada. Tu solo quieres devolver un objeto valido o un error, no entiendo que tiene de dificil escribir una funcion.

#23vago_21:

oversized

es la sintaxis de mierda de java y scala... en otros lenguajes un ADT y un enum es EXACTAMENTE lo mismo, y te haran el pattern match exhaustivo en tiempo de compilacion...

enum Type {
    TypeA,
    TypeB,
}

fun match(type Type) {
   match type {
    TypeA => {...},
    TypeB => {...},
  }
}

De nuevo, scala y java son una porqueria y para algo tan facil tienes que hacer diez mil filigranas.

Si esto es practico o no pues depende de lo que quieras hacer... solo es una union y te sirve para tomar decisiones... que tiene de raro?

1 respuesta
B

#24 imagina que sí, que usas un smart constructor porque tus compañeros son unos monos ¿qué tiene de malo? estás preveniendo errores

Por otro lado, en el smart constructor devuelves un Option, no siempre success.

Ejemplo:

class Person private (val name: String, val age: Int)

object Person {
  def create(name: String, age: Int): Option[Person] = {
    if (name.nonEmpty && age >= 0) {
      Some(new Person(name, age))
    } else {
      None
    }
  }
}
2 respuestas
desu
#25vago_21:

¿qué tiene de malo?

nada, solo es un patron emergente porque tu lenguaje es malo y la unica manera de instanciar una clase es un caso de siempre exito

#25vago_21:

en el smart constructor devuelves un Option, no siempre success.

lo que he dicho es que el constructor por defecto siempre es success.

class Person (val name: String, val age: Int)

val p = new Person("foo", 123) // el constructor por defecto siempre devuelve una instancia o excepcion.

por eso requieres una funcion aparte. devolver un option no me parece buena practica tampoco, prefiero devolver el error.

de que te sirve en tu ejemplo devolver un None, mucho mejor devolver el error, voy a usar un Try porque es lo primero que he visto en google y la sintaxis es pseud-scala:

class Person private (val name: String, val age: Int)

object Person {
  def create(name: String, age: Int): Try[Person] = {
   if (name.Empty) {
     throw Exception("name was empty")
   {
   if age <= 0 {
     throw Exception("age %d, age must be > 0", age)
   }
   new Person(name, age))
  }

  def usePerson() {
   Person.create("name", 125) match {
      case Success(p) => println(i)
      case Failure(s) => println(s"Failed. Reason: $s")
     }
  }
}

de hecho puedes tener un applicativo con eithers que te comprueve todas las condiciones y devolver una lista de errores o en el success una Person.

MTX_Anubis

#25 Lo que haces en ese ejemplo es una mierda como la copa de un pito y estoy con @desu 100%

Si tiene que dar error pues lo da y ya está. Eso de usar Option/Maybe por doquier qué mono lo ha enseñado?

1 respuesta
desu

#27 A mi lo que mas rabia me da es que "inventen terminologia" como "smart constructor" o "ADT" para escribir blogs y libros. Los tontos de Codely y demas personajes de Youtube se frotan las manos.

Es una puta funcion y hacer un switch de enums que tiene de especial o raro? Es que no entiendo las dudas.

La Option no deja de ser un puntero. No les gusta hacer if *pointer == null y aplauden con las orejas al hacer optional.map(...) como si luego hubiese alguna diferencia. Que por cierto, no se en Scala, pero en Java los Optional son nullables como todo porque son referencias XD

edit, Option es nullable, asi que siempre te comeras el if de comprovar si es null o no:

1 respuesta
MTX_Anubis

#28 En java todo es nullable. En Scala también pero porque hay que pasar por el aro de la JVM. No se si te refieres a que un Some puede tener null pero en Scala también puede ser Some(null) (normalmente cuando interactua con Java y cosas así)

Y mierdas como estas en Scala tienes mil y por eso pasó de ser un lenguaje que me gustaba a uno al que quiero tener bien lejos xD.

Vamos si quisiera desarrollar funcional de iría a F# de cabeza y no estas mierdas hibridas.

1 respuesta
desu
#29MTX_Anubis:

Y mierdas como estas en Scala tienes mil y por eso pasó de ser un lenguaje que me gustaba a uno al que quiero tener bien lejos xD.

Y Kotlin igual, y Clojure... porque aunque todo sea perfecto cuando solo es ese lenguaje siempre te tocara pringar el interactuar con Java. Y en el mundo real siempre hay que pringar al tocar frameworks. Yo por eso recomiendo Java directamente y a tomar por culo.

#29MTX_Anubis:

Vamos si quisiera desarrollar funcional de iría a F# de cabeza y no estas mierdas hibridas.

Pff no se, no conozco el ecosistema de C#. Yo haria Ocaml... Pero como siempre digo. En C tambien puedes hacer funcional eh. Y el borrow checker de Rust es un sistema funcional por ejemplo... Si lo que quieres es un compilador con tipado HM pues usa algo que lo tenga, no necesitas hacer boberias funcionales. Por eso prefiero Ocaml.

Usuarios habituales