Scala ( / ˈ s k ɑː l ɑː / SKAH -lah ) [7] [8] es un lenguaje de programación de propósito general de alto nivel , tipado estáticamente y fuerte que admite tanto la programación orientada a objetos como la programación funcional . Diseñado para ser conciso, [9] muchas de las decisiones de diseño de Scala tienen como objetivo abordar las críticas a Java . [6]
El código fuente de Scala se puede compilar en bytecode de Java y ejecutarse en una máquina virtual Java (JVM). Scala también se puede transpilar a JavaScript para ejecutarse en un navegador, o compilarse directamente en un ejecutable nativo. Cuando se ejecuta en la JVM, Scala proporciona interoperabilidad de lenguaje con Java para que las bibliotecas escritas en cualquiera de los lenguajes puedan referenciarse directamente en código Scala o Java. [10] Al igual que Java, Scala está orientado a objetos y utiliza una sintaxis denominada llave que es similar al lenguaje C. Desde Scala 3, también existe una opción para utilizar la regla del lado opuesto (sangría) para estructurar bloques , y se recomienda su uso. Martin Odersky ha dicho que este resultó ser el cambio más productivo introducido en Scala 3. [11]
A diferencia de Java, Scala tiene muchas características de los lenguajes de programación funcional (como Scheme , Standard ML y Haskell ), incluyendo currying , inmutabilidad , evaluación diferida y coincidencia de patrones . También tiene un sistema de tipos avanzado que admite tipos de datos algebraicos , covarianza y contravarianza , tipos de orden superior (pero no tipos de rango superior ), tipos anónimos , sobrecarga de operadores , parámetros opcionales , parámetros nombrados , cadenas sin formato y una versión experimental de solo excepciones de efectos algebraicos que puede verse como una versión más poderosa de las excepciones comprobadas de Java . [12]
El nombre Scala es una combinación de escalable y lenguaje , lo que significa que está diseñado para crecer con las demandas de sus usuarios. [13]
Historia
El diseño de Scala comenzó en 2001 en la Escuela Politécnica Federal de Lausana (EPFL) (en Lausana , Suiza ) por Martin Odersky . Fue la continuación del trabajo en Funnel, un lenguaje de programación que combina ideas de programación funcional y redes de Petri . [14] Odersky trabajó anteriormente en Generic Java y javac , el compilador Java de Sun. [14]
Después de un lanzamiento interno a finales de 2003, Scala se lanzó públicamente a principios de 2004 en la plataforma Java , [15] [6] [14] [16] Una segunda versión (v2.0) siguió en marzo de 2006. [6]
El 17 de enero de 2011, el equipo de Scala ganó una subvención de investigación de cinco años por más de 2,3 millones de euros del Consejo Europeo de Investigación . [17] El 12 de mayo de 2011, Odersky y sus colaboradores lanzaron Typesafe Inc. (posteriormente rebautizada como Lightbend Inc. ), una empresa para proporcionar soporte comercial, formación y servicios para Scala. Typesafe recibió una inversión de 3 millones de dólares en 2011 de Greylock Partners . [18] [19] [20] [21]
Plataformas y licencias
Scala se ejecuta en la plataforma Java ( máquina virtual Java ) y es compatible con los programas Java existentes . [15] Como las aplicaciones de Android generalmente se escriben en Java y se traducen del bytecode de Java al bytecode de Dalvik (que puede traducirse aún más a código de máquina nativo durante la instalación) cuando se empaquetan, la compatibilidad de Scala con Java lo hace adecuado para el desarrollo de Android, más aún cuando se prefiere un enfoque funcional. [22]
La distribución del software de referencia Scala, incluido el compilador y las bibliotecas, se publica bajo la licencia Apache . [23]
Otros compiladores y objetivos
Scala.js es un compilador de Scala que compila en JavaScript, lo que permite escribir programas en Scala que se pueden ejecutar en navegadores web o Node.js. [24] El compilador, en desarrollo desde 2013, se anunció que ya no era experimental en 2015 (v0.6). La versión v1.0.0-M1 se lanzó en junio de 2018 y la versión 1.1.1 en septiembre de 2020. [ 25]
Scala Native es un compilador de Scala que apunta a la infraestructura del compilador LLVM para crear código ejecutable que utiliza un entorno de ejecución administrado liviano, que utiliza el recolector de basura Boehm . El proyecto está dirigido por Denys Shabalin y tuvo su primer lanzamiento, 0.1, el 14 de marzo de 2017. El desarrollo de Scala Native comenzó en 2015 con el objetivo de ser más rápido que la compilación justo a tiempo para la JVM al eliminar la compilación inicial del código en tiempo de ejecución y también brindar la capacidad de llamar a rutinas nativas directamente. [26] [27]
En junio de 2004 se lanzó un compilador de referencia de Scala dirigido a .NET Framework y su Common Language Runtime , [14] pero se abandonó oficialmente en 2012. [28]
Ejemplos
Ejemplo de "Hola mundo"
El programa Hola Mundo escrito en Scala 3 tiene esta forma:
@main def main () = println ( "¡Hola, mundo!" )
A diferencia de la aplicación independiente Hello World para Java , no hay declaración de clase y nada se declara como estático.
Cuando el programa se almacena en el archivo HelloWorld.scala , el usuario lo compila con el comando:
$ scalac HolaMundo.scala
y lo ejecuta con
$ scala Hola Mundo
Esto es análogo al proceso de compilación y ejecución de código Java. De hecho, el modelo de compilación y ejecución de Scala es idéntico al de Java, lo que lo hace compatible con herramientas de compilación de Java como Apache Ant .
Una versión más corta del programa Scala "Hola Mundo" es:
println ( "¡Hola, mundo!" )
Scala incluye un shell interactivo y soporte para scripts. [29] Guardado en un archivo llamado HelloWorld2.scala, se puede ejecutar como un script usando el comando:
$ scala HolaMundo2.scala
Los comandos también se pueden ingresar directamente en el intérprete de Scala, usando la opción -e :
$ scala -e 'println("¡Hola, mundo!")'
Las expresiones se pueden ingresar de forma interactiva en el REPL :
$ scala
Bienvenido a Scala 2.12.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_131).
Escriba expresiones para su evaluación. O pruebe :help.
scala> Lista(1, 2, 3).map(x => x * x)
res0: Lista[Int] = Lista(1, 4, 9)
escala>
Ejemplo básico
El siguiente ejemplo muestra las diferencias entre la sintaxis de Java y Scala. La función mathFunction toma un número entero, lo eleva al cuadrado y luego suma la raíz cúbica de ese número al logaritmo natural de ese número, devolviendo el resultado (es decir, ):
Algunas diferencias sintácticas en este código son:
- Scala no requiere punto y coma (;) para finalizar las declaraciones.
- Los tipos de valor se escriben con mayúscula (en mayúscula inicial):
Int, Double, Booleanen lugar deint, double, boolean. - Los tipos de parámetros y retornos siguen, como en Pascal , en lugar de preceder como en C.
- Los métodos deben estar precedidos por
def. - Las variables locales o de clase deben estar precedidas por
val(indica una variable inmutable ) ovar(indica una variable mutable ). - El
returnoperador no es necesario en una función (aunque está permitido); el valor de la última declaración o expresión ejecutada normalmente es el valor de la función. - En lugar del operador de conversión de Java
(Type) foo, Scala utilizafoo.asInstanceOf[Type], o una función especializada comotoDoubleotoInt. - En lugar de Java
import foo.*;, Scala utilizaimport foo._. - Una función o un método
foo()también se pueden llamar como justfoo; un métodothread.send(signo)también se pueden llamar como justthread send signo; y un métodofoo.toString()también se pueden llamar como justfoo toString.
Estas relajaciones sintácticas están diseñadas para permitir el soporte de lenguajes específicos del dominio .
Algunas otras diferencias sintácticas básicas:
- Las referencias de matriz se escriben como llamadas de función, por ejemplo,
array(i)en lugar dearray[i]. (Internamente en Scala, la primera se expande en array.apply(i) que devuelve la referencia) - Los tipos genéricos se escriben como eg
List[String]en lugar de comoList<String>. - En lugar del pseudotipo , Scala tiene la clase singleton
voidreal (ver a continuación).Unit
Ejemplo con clases
El siguiente ejemplo contrasta la definición de clases en Java y Scala.
El código anterior muestra algunas de las diferencias conceptuales entre el manejo de clases de Java y Scala:
- Scala no tiene variables o métodos estáticos. En cambio, tiene objetos singleton , que son esencialmente clases con una sola instancia. Los objetos singleton se declaran usando
objecten lugar declass. Es común colocar variables y métodos estáticos en un objeto singleton con el mismo nombre que el nombre de la clase, que luego se conoce como objeto complementario . [15] (La clase subyacente para el objeto singleton tiene un$adjunto. Por lo tanto, paraclass Foocon objeto complementarioobject Foo, bajo el capó hay una claseFoo$que contiene el código del objeto complementario, y se crea un objeto de esta clase, usando el patrón singleton ). - En lugar de parámetros de constructor, Scala tiene parámetros de clase , que se colocan en la clase, de manera similar a los parámetros de una función. Cuando se declaran con un modificador
valovar, los campos también se definen con el mismo nombre y se inicializan automáticamente a partir de los parámetros de clase. (En esencia, el acceso externo a los campos públicos siempre pasa por métodos de acceso (getter) y mutador (setter), que se crean automáticamente. La función de acceso tiene el mismo nombre que el campo, por lo que en el ejemplo anterior no es necesario declarar explícitamente los métodos de acceso). Tenga en cuenta que también se pueden declarar constructores alternativos, como en Java. El código que iría al constructor predeterminado (aparte de inicializar las variables miembro) va directamente al nivel de clase. - En Scala es posible definir operadores utilizando símbolos como nombres de métodos. En lugar de
addPoint, el ejemplo de Scala define+=, que luego se invoca con notación infija comogrid += this. - La visibilidad predeterminada en Scala es
public.
Características (con referencia a Java)
Scala tiene el mismo modelo de compilación que Java y C# , es decir, compilación separada y carga dinámica de clases , de modo que el código Scala puede llamar a las bibliotecas Java.
Las características operativas de Scala son las mismas que las de Java. El compilador de Scala genera un código de bytes que es casi idéntico al generado por el compilador de Java. [15] De hecho, el código de Scala se puede descompilar en código Java legible, con la excepción de ciertas operaciones de construcción. Para la máquina virtual Java (JVM), el código de Scala y el código de Java son indistinguibles. La única diferencia es una biblioteca de tiempo de ejecución adicional, scala-library.jar. [30]
Scala añade una gran cantidad de características en comparación con Java y tiene algunas diferencias fundamentales en su modelo subyacente de expresiones y tipos, lo que hace que el lenguaje sea teóricamente más claro y elimina varios casos especiales en Java. Desde la perspectiva de Scala, esto es importante en la práctica porque varias de las características añadidas en Scala también están disponibles en C#.
Flexibilidad sintáctica
Como se mencionó anteriormente, Scala tiene una gran flexibilidad sintáctica en comparación con Java. A continuación se muestran algunos ejemplos:
- Los puntos y comas no son necesarios; las líneas se unen automáticamente si comienzan o terminan con un token que normalmente no puede venir en esta posición, o si hay paréntesis o corchetes sin cerrar.
- Cualquier método puede utilizarse como operador infijo , por ejemplo
"%d apples".format(num), y"%d apples" format numson equivalentes. De hecho, los operadores aritméticos como+y<<se tratan como cualquier otro método, ya que se permite que los nombres de funciones consten de secuencias de símbolos arbitrarios (con algunas excepciones para elementos como paréntesis, corchetes y llaves que deben manejarse de manera especial); el único tratamiento especial que experimentan estos métodos nombrados con símbolos se refiere al manejo de la precedencia. - Los métodos
applyyupdatetienen formas sintácticas cortas.foo()—dondefooes un valor (un objeto singleton o una instancia de clase)— es la abreviatura defoo.apply(), yfoo() = 42es la abreviatura defoo.update(42). De manera similar,foo(42)es la abreviatura defoo.apply(42), yfoo(4) = 2es la abreviatura defoo.update(4, 2). Esto se utiliza para clases de colección y se extiende a muchos otros casos, como las celdas STM . - Scala distingue entre métodos sin paréntesis (
def foo = 42) y con paréntesis vacíos (def foo() = 42). Al llamar a un método con paréntesis vacíos, se pueden omitir los paréntesis, lo que resulta útil al llamar a bibliotecas Java que no conocen esta distinción, por ejemplo, utilizandofoo.toStringen lugar defoo.toString(). Por convención, un método debe definirse con paréntesis vacíos cuando realiza efectos secundarios . - Los nombres de métodos que terminan en dos puntos (
:) esperan el argumento en el lado izquierdo y el receptor en el lado derecho. Por ejemplo, the4 :: 2 :: Niles lo mismo queNil.::(2).::(4), la primera forma corresponde visualmente al resultado (una lista con el primer elemento 4 y el segundo elemento 2). - Las variables del cuerpo de la clase se pueden implementar de forma transparente como métodos getter y setter independientes. Para
trait FooLike { var bar: Int }, una implementación puede ser . El sitio de llamada aún podrá usar un .object Foo extends FooLike { private var x = 0; def bar = x; def bar_=(value: Int) { x = value }} } }foo.bar = 42 - Se permite el uso de llaves en lugar de paréntesis en las llamadas a métodos. Esto permite implementaciones de bibliotecas puras de nuevas estructuras de control. [31] Por ejemplo,
breakable { ... if (...) break() ... }parecebreakableuna palabra clave definida por el lenguaje, pero en realidad es solo un método que toma un argumento thunk . Los métodos que toman thunks o funciones a menudo los colocan en una segunda lista de parámetros, lo que permite mezclar la sintaxis de paréntesis y llaves:Vector.fill(4) { math.random }es lo mismo queVector.fill(4)(math.random). La variante de llaves permite que la expresión abarque varias líneas. - Las expresiones for (explicadas más adelante) pueden admitir cualquier tipo que defina métodos monádicos como
map,flatMapyfilter.
Por sí solas, estas opciones pueden parecer cuestionables, pero en conjunto sirven para permitir que se definan lenguajes específicos de dominio en Scala sin necesidad de extender el compilador. Por ejemplo, la sintaxis especial de Erlangactor ! message para enviar un mensaje a un actor, ie , puede implementarse (y se implementa) en una biblioteca de Scala sin necesidad de extensiones de lenguaje.
Sistema de tipos unificado
Java hace una distinción clara entre tipos primitivos (por ejemplo, intand boolean) y tipos de referencia (cualquier clase ). Solo los tipos de referencia forman parte del esquema de herencia, que derivan de java.lang.Object. En Scala, todos los tipos heredan de una clase de nivel superior Any, cuyos hijos inmediatos son AnyVal(tipos de valor, como Intand Boolean) y AnyRef(tipos de referencia, como en Java). Esto significa que la distinción de Java entre tipos primitivos y tipos encajonados (por ejemplo, intvs. Integer) no está presente en Scala; el encajonamiento y el desencajonamiento son completamente transparentes para el usuario. Scala 2.10 permite que el usuario defina nuevos tipos de valor.
Expresiones for
En lugar de los bucles " foreach " de Java para recorrer un iterador, Scala tiene forexpresiones for, que son similares a las comprensiones de listas en lenguajes como Haskell , o una combinación de comprensiones de listas y expresiones generadoras en Python . Las expresiones for que usan la yieldpalabra clave permiten generar una nueva colección iterando sobre una existente, y devuelven una nueva colección del mismo tipo. El compilador las traduce en una serie de llamadas map, flatMapy filter. Donde yieldno se usa , el código se aproxima a un bucle de estilo imperativo, traduciendo a foreach.
Un ejemplo sencillo es:
val s = para ( x <- 1 a 25 si x * x > 50 ) rendimiento 2 * x
El resultado de ejecutarlo es el siguiente vector:
Vector(16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50)
(Tenga en cuenta que la expresión 1 to 25no es una sintaxis especial. El método toestá definido en la biblioteca Scala estándar como un método de extensión de números enteros, utilizando una técnica conocida como conversiones implícitas [32] que permite agregar nuevos métodos a tipos existentes).
Un ejemplo más complejo de iteración sobre un mapa es:
// Dado un mapa que especifica los usuarios de Twitter mencionados en un conjunto de tweets,
// y la cantidad de veces que cada usuario fue mencionado, busque los usuarios
// en un mapa de políticos conocidos y devuelva un nuevo mapa que proporcione solo los
políticos demócratas (como objetos, en lugar de cadenas).
val dem_mentions = for ( mention , times ) <- mentions account <- accounts . get ( mention ) if account . party == "Democratic" yield ( account , times )
La expresión (mention, times) <- mentionses un ejemplo de coincidencia de patrones (ver más abajo). La iteración sobre un mapa devuelve un conjunto de tuplas de clave-valor , y la coincidencia de patrones permite que las tuplas se desestructuran fácilmente en variables separadas para la clave y el valor. De manera similar, el resultado de la comprensión también devuelve tuplas de clave-valor, que se vuelven a construir automáticamente en un mapa porque el objeto de origen (de la variable mentions) es un mapa. Tenga en cuenta que si mentionsen cambio se incluyera una lista, un conjunto, una matriz u otra colección de tuplas, exactamente el mismo código anterior generaría una nueva colección del mismo tipo.
Tendencias funcionales
Si bien Scala admite todas las características orientadas a objetos disponibles en Java (y, de hecho, las amplía de diversas maneras), también proporciona una gran cantidad de capacidades que normalmente solo se encuentran en lenguajes de programación funcionales . En conjunto, estas características permiten que los programas de Scala se escriban en un estilo casi completamente funcional y también permiten mezclar estilos funcionales y orientados a objetos.
Algunos ejemplos son:
- No hay distinción entre afirmaciones y expresiones
- Inferencia de tipos
- Funciones anónimas con semántica de captura (es decir, cierres )
- Variables y objetos inmutables
- Evaluación perezosa
- Continuaciones delimitadas (desde 2.8)
- Funciones de orden superior
- Funciones anidadas
- Zurra
- Coincidencia de patrones
- Tipos de datos algebraicos (a través de clases de casos )
- Tuplas
Todo es una expresión
A diferencia de C o Java , pero similar a lenguajes como Lisp , Scala no hace distinción entre declaraciones y expresiones . Todas las declaraciones son, de hecho, expresiones que evalúan a algún valor. Las funciones que se declararían como de retorno voiden C o Java, y las declaraciones como whileesas lógicamente no devuelven un valor, se consideran en Scala como de retorno del tipo Unit, que es un tipo singleton , con solo un objeto de ese tipo. Las funciones y operadores que nunca retornan en absoluto (por ejemplo, el throwoperador o una función que siempre sale de forma no local utilizando una excepción) tienen lógicamente un tipo de retorno Nothing, un tipo especial que no contiene objetos; es decir, un tipo inferior , es decir, una subclase de cada tipo posible. (Esto a su vez hace que el tipo Nothingsea compatible con todos los tipos, lo que permite que la inferencia de tipos funcione correctamente). [33]
De manera similar, una if-then-else"declaración" es en realidad una expresión que produce un valor, es decir, el resultado de evaluar una de las dos ramas. Esto significa que dicho bloque de código se puede insertar donde se desee una expresión, lo que evita la necesidad de un operador ternario en Scala:
Por razones similares, returnlas declaraciones son innecesarias en Scala y, de hecho, no se recomiendan. Al igual que en Lisp , la última expresión de un bloque de código es el valor de ese bloque de código y, si el bloque de código es el cuerpo de una función, la función lo devolverá.
Para dejar en claro que todas las funciones son expresiones, incluso los métodos que retornan Unitse escriben con un signo igual.
def printValue ( x : String ): Unit = println ( "Me comí un %s" .format ( x ) )
o equivalentemente (con inferencia de tipo y omitiendo la nueva línea innecesaria):
def printValue ( x : String ) = println ( "Me comí un %s" formato x )
Inferencia de tipos
Debido a la inferencia de tipos , el tipo de variables, valores de retorno de funciones y muchas otras expresiones se pueden omitir normalmente, ya que el compilador puede deducirlo. Algunos ejemplos son val x = "foo"(para una constante inmutable o un objeto inmutable ) o var x = 1.5(para una variable cuyo valor se puede cambiar más tarde). La inferencia de tipos en Scala es esencialmente local, en contraste con el algoritmo Hindley-Milner más global utilizado en Haskell, ML y otros lenguajes más puramente funcionales. Esto se hace para facilitar la programación orientada a objetos. El resultado es que todavía es necesario declarar ciertos tipos (en particular, los parámetros de función y los tipos de retorno de funciones recursivas ), por ejemplo
def formatApples ( x : Int ) = "Comí %d manzanas " .format ( x )
o (con un tipo de retorno declarado para una función recursiva)
def factorial ( x : Int ): Int = si x == 0 entonces 1 de lo contrario x * factorial ( x - 1 )
Funciones anónimas
En Scala, las funciones son objetos y existe una sintaxis conveniente para especificar funciones anónimas . Un ejemplo es la expresión x => x < 2, que especifica una función con un parámetro, que compara su argumento para ver si es menor que 2. Es equivalente a la forma Lisp (lambda (x) (< x 2)). Tenga en cuenta que ni el tipo de xni el tipo de retorno necesitan especificarse explícitamente, y generalmente se pueden inferir por inferencia de tipo ; pero se pueden especificar explícitamente, por ejemplo, as (x: Int) => x < 2o even (x: Int) => (x < 2): Boolean.
Las funciones anónimas se comportan como verdaderos cierres , ya que capturan automáticamente cualquier variable que esté disponible léxicamente en el entorno de la función que las contiene. Esas variables estarán disponibles incluso después de que la función que las contiene regrese y, a diferencia del caso de las clases internas anónimas de Java , no es necesario declararlas como finales. (Incluso es posible modificar dichas variables si son mutables, y el valor modificado estará disponible la próxima vez que se llame a la función anónima).
Una forma aún más corta de función anónima utiliza variables de marcador de posición : por ejemplo, la siguiente:
list map { x => sqrt(x) }
Se puede escribir de forma más concisa como
list map { sqrt(_) }
o incluso
list map sqrt
Inmutabilidad
Scala impone una distinción entre variables mutables e inmutables. Las variables mutables se declaran utilizando la varpalabra clave y los valores inmutables se declaran utilizando la valpalabra clave. Una variable declarada utilizando la valpalabra clave no se puede reasignar de la misma manera que una variable declarada utilizando la finalpalabra clave no se puede reasignar en Java. valLos s son solo inmutables superficialmente, es decir, no se garantiza que un objeto al que hace referencia un val sea inmutable en sí mismo.
Sin embargo, por convención se fomenta el uso de clases inmutables, y la biblioteca estándar de Scala proporciona un amplio conjunto de clases de colección inmutables. Scala proporciona variantes mutables e inmutables de la mayoría de las clases de colección, y la versión inmutable siempre se utiliza a menos que la versión mutable se importe explícitamente. [34] Las variantes inmutables son estructuras de datos persistentes que siempre devuelven una copia actualizada de un objeto antiguo en lugar de actualizar el objeto antiguo de forma destructiva en su lugar. Un ejemplo de esto son las listas enlazadas inmutables , en las que anteponer un elemento a una lista se hace devolviendo un nuevo nodo de lista que consiste en el elemento y una referencia a la cola de la lista. Anexar un elemento a una lista solo se puede hacer anteponiendo todos los elementos de la lista antigua a una nueva lista con solo el nuevo elemento. De la misma manera, insertar un elemento en el medio de una lista copiará la primera mitad de la lista, pero mantendrá una referencia a la segunda mitad de la lista. Esto se llama compartición estructural. Esto permite una concurrencia muy fácil: no se necesitan bloqueos ya que nunca se modifican los objetos compartidos. [35]
Evaluación perezosa (no estricta)
La evaluación es estricta ("eager") por defecto. En otras palabras, Scala evalúa las expresiones tan pronto como están disponibles, en lugar de cuando se necesitan. Sin embargo, es posible declarar una variable no estricta ("lazy") con la lazypalabra clave, lo que significa que el código para producir el valor de la variable no se evaluará hasta la primera vez que se haga referencia a la variable. También existen colecciones no estrictas de varios tipos (como el tipo Stream, una lista enlazada no estricta), y cualquier colección puede convertirse en no estricta con el viewmétodo . Las colecciones no estrictas proporcionan un buen ajuste semántico a cosas como los datos producidos por el servidor, donde la evaluación del código para generar elementos posteriores de una lista (que a su vez desencadena una solicitud a un servidor, posiblemente ubicado en otro lugar de la web) solo ocurre cuando los elementos son realmente necesarios.
Recursión de cola
Los lenguajes de programación funcional suelen ofrecer optimización de llamadas de cola para permitir un uso extensivo de la recursión sin problemas de desbordamiento de pila . Las limitaciones en el bytecode de Java complican la optimización de llamadas de cola en la JVM. En general, una función que se llama a sí misma con una llamada de cola se puede optimizar, pero las funciones recursivas entre sí no. Se han sugerido trampolines como una solución alternativa. [36] La biblioteca Scala ofrece compatibilidad con trampolines con el objeto scala.util.control.TailCallsdesde Scala 2.8.0 (publicada el 14 de julio de 2010). Una función puede opcionalmente anotarse con @tailrec, en cuyo caso no se compilará a menos que sea recursiva de cola. [37]
Un ejemplo de esta optimización podría implementarse utilizando la definición factorial . Por ejemplo, la versión recursiva del factorial:
def factorial ( n : Int ): Int = si n == 0 entonces 1 de lo contrario n * factorial ( n - 1 )
Se podría optimizar la versión recursiva de cola de la siguiente manera:
@tailrec
def factorial ( n : Int , accum : Int ): Int = si n == 0 entonces accum else factorial ( n - 1 , n * accum )
Sin embargo, esto podría comprometer la componibilidad con otras funciones debido al nuevo argumento en su definición, por lo que es común usar cierres para preservar su firma original:
def factorial ( n : Int ): Int =
@tailrec
def bucle ( actual : Int , acumulado : Int ): Int =
si n == 0 entonces acum
else bucle ( actual - 1 , n * accum )
loop ( n , 1 ) // Llamada al cierre usando el caso base
factorial final
Esto garantiza la optimización de llamadas finales y, por lo tanto, evita un error de desbordamiento de pila.
Clases de casos y coincidencia de patrones
Scala tiene soporte integrado para la comparación de patrones , que puede considerarse como una versión más sofisticada y extensible de una declaración switch , donde se pueden comparar tipos de datos arbitrarios (en lugar de solo tipos simples como números enteros, booleanos y cadenas), incluido el anidamiento arbitrario. Se proporciona un tipo especial de clase conocida como clase case , que incluye soporte automático para la comparación de patrones y se puede usar para modelar los tipos de datos algebraicos utilizados en muchos lenguajes de programación funcional. (Desde la perspectiva de Scala, una clase case es simplemente una clase normal para la cual el compilador agrega automáticamente ciertos comportamientos que también se podrían proporcionar manualmente, por ejemplo, definiciones de métodos que proporcionan comparaciones profundas y hash, y desestructuración de una clase case en sus parámetros de constructor durante la comparación de patrones).
Un ejemplo de una definición del algoritmo de ordenación rápida que utiliza coincidencia de patrones es el siguiente:
def qsort ( lista : Lista [ Int ]): Lista [ Int ] = lista match caso Nil => caso Nil pivot :: tail => val ( más pequeño , resto ) = tail.partition ( _ < pivot ) qsort ( más pequeño ) ::: pivot :: qsort ( resto )
La idea aquí es dividir una lista en los elementos menores que un pivote y los elementos no menores, ordenar recursivamente cada parte y pegar los resultados junto con el pivote en el medio. Esto utiliza la misma estrategia de dividir y vencer de mergesort y otros algoritmos de ordenamiento rápido.
El matchoperador se utiliza para hacer una comparación de patrones en el objeto almacenado en list. Cada caseexpresión se prueba por turno para ver si coincide, y la primera coincidencia determina el resultado. En este caso, Nilsolo coincide con el objeto literal Nil, pero pivot :: tailcoincide con una lista no vacía y, simultáneamente, desestructura la lista según el patrón dado. En este caso, el código asociado tendrá acceso a una variable local llamada pivotque contiene el encabezado de la lista y a otra variable tailque contiene el final de la lista. Tenga en cuenta que estas variables son de solo lectura y son semánticamente muy similares a los enlaces de variables establecidos utilizando el letoperador en Lisp y Scheme.
La comparación de patrones también se produce en las declaraciones de variables locales. En este caso, el valor de retorno de la llamada a tail.partitiones una tupla , en este caso, dos listas. (Las tuplas se diferencian de otros tipos de contenedores, por ejemplo, las listas, en que siempre tienen un tamaño fijo y los elementos pueden ser de diferentes tipos, aunque en este caso ambos son iguales). La comparación de patrones es la forma más sencilla de obtener las dos partes de la tupla.
El formulario _ < pivotes una declaración de una función anónima con una variable de marcador de posición; consulte la sección anterior sobre funciones anónimas.
Aparecen los operadores de lista ::(que añaden un elemento al principio de una lista, de forma similar a lo que ocurre consen Lisp y Scheme) y :::(que unen dos listas, de forma similar a lo que ocurre appenden Lisp y Scheme). A pesar de las apariencias, no hay nada "integrado" en ninguno de estos operadores. Como se especificó anteriormente, cualquier cadena de símbolos puede servir como nombre de función, y un método aplicado a un objeto puede escribirse en estilo "infijo" sin el punto ni los paréntesis. La línea anterior está escrita así:
qsort(smaller) ::: pivot :: qsort(rest)
También podría escribirse así:
qsort(rest).::(pivot).:::(qsort(smaller))
en una notación de llamada de método más estándar. (Los métodos que terminan con dos puntos son asociativos por la derecha y se vinculan al objeto situado a la derecha).
Funciones parciales
En el ejemplo de coincidencia de patrones anterior, el cuerpo del matchoperador es una función parcial , que consta de una serie de caseexpresiones, en la que prevalece la primera expresión coincidente, de forma similar al cuerpo de una sentencia switch . Las funciones parciales también se utilizan en la parte de manejo de excepciones de una trysentencia:
Intente ... capture el caso nfe : NumberFormatException => { println ( nfe ); List ( 0 ) } caso _ => Nil
Por último, una función parcial se puede utilizar sola y el resultado de llamarla es equivalente a realizar una operación matchsobre ella. Por ejemplo, el código anterior para quicksort se puede escribir así:
val qsort : Lista [ Int ] => Lista [ Int ] = caso Nil => caso Nil pivote :: tail => val ( menor , resto ) = tail . partición ( _ < pivote ) qsort ( menor ) ::: pivote :: qsort ( resto )
Aquí se declara una variable de solo lectura cuyo tipo es una función de listas de números enteros a listas de números enteros, y se la vincula a una función parcial. (Tenga en cuenta que el parámetro único de la función parcial nunca se declara ni se nombra explícitamente). Sin embargo, aún podemos llamar a esta variable exactamente como si fuera una función normal:
scala > qsort ( Lista ( 6 , 2 , 5 , 9 )) res32 : Lista [ Int ] = Lista ( 2 , 5 , 6 , 9 )
Extensiones orientadas a objetos
Scala es un lenguaje orientado a objetos puro en el sentido de que cada valor es un objeto . Los tipos de datos y los comportamientos de los objetos se describen mediante clases y rasgos . Las abstracciones de clase se extienden mediante subclases y un mecanismo de composición flexible basado en mixin para evitar los problemas de herencia múltiple .
Los rasgos son el reemplazo de Scala para las interfaces de Java . Las interfaces en las versiones de Java anteriores a la 8 están altamente restringidas y solo pueden contener declaraciones de funciones abstractas. Esto ha llevado a críticas de que proporcionar métodos convenientes en las interfaces es complicado (los mismos métodos deben reimplementarse en cada implementación) y extender una interfaz publicada de una manera compatible con versiones anteriores es imposible. Los rasgos son similares a las clases mixin en que tienen casi todo el poder de una clase abstracta regular, careciendo solo de parámetros de clase (el equivalente de Scala a los parámetros del constructor de Java), ya que los rasgos siempre se mezclan con una clase. El superoperador se comporta de manera especial en los rasgos, lo que permite encadenarlos utilizando composición además de herencia. El siguiente ejemplo es un sistema de ventanas simple:
clase abstracta Ventana : // def abstracta draw ()
clase SimpleWindow extiende Window : def draw () println ( "in SimpleWindow" ) // dibuja una ventana básica
El rasgo WindowDecoration extiende Window
rasgo HorizontalScrollbarDecoration extiende WindowDecoration : // "abstract override" es necesario aquí para que "super()" funcione porque la función padre es abstracta. Si fuera concreta, bastaría con "override" normal. abstract override def draw () println ( "in HorizontalScrollbarDecoration" ) super . draw () // ahora dibuja una barra de desplazamiento horizontal
rasgo VerticalScrollbarDecoration extiende WindowDecoration : abstract override def draw () println ( "en VerticalScrollbarDecoration" ) super . draw () // ahora dibuja una barra de desplazamiento vertical
rasgo TitleDecoration extiende WindowDecoration : abstract override def draw () println ( "in TitleDecoration" ) super . draw () // ahora dibuja la barra de título
Una variable puede declararse así:
val mywin = new SimpleWindow con VerticalScrollbarDecoration con HorizontalScrollbarDecoration con TitleDecoration
El resultado de la llamada mywin.draw()es:
en TítuloDecoración en Barra de desplazamiento horizontalDecoración en Barra de desplazamiento verticalDecoración en Ventana simple
En otras palabras, la llamada a drawprimero ejecutó el código en TitleDecoration(el último rasgo mezclado), luego (a través de las super()llamadas) se enhebró de nuevo a través de los otros rasgos mezclados y finalmente al código en Window, aunque ninguno de los rasgos heredó de otro . Esto es similar al patrón decorador , pero es más conciso y menos propenso a errores, ya que no requiere encapsular explícitamente la ventana principal, reenviar explícitamente funciones cuya implementación no se cambia o confiar en la inicialización en tiempo de ejecución de las relaciones de entidad. En otros lenguajes, se podría lograr un efecto similar en tiempo de compilación con una larga cadena lineal de herencia de implementación , pero con la desventaja en comparación con Scala de que se tendría que declarar una cadena de herencia lineal para cada combinación posible de los mix-ins.
Sistema de tipos expresivos
Scala está equipado con un sistema de tipos estáticos expresivo que, en su mayor parte, refuerza el uso seguro y coherente de las abstracciones. Sin embargo, el sistema de tipos no es sólido . [38] En particular, el sistema de tipos admite:
- Clases y tipos abstractos como miembros de objetos
- Tipos estructurales
- Tipos dependientes de la ruta
- Tipos de compuestos
- Referencias a uno mismo explícitamente tipificadas
- Clases genéricas
- Métodos polimórficos
- Límites de tipo superior e inferior
- Diferencia
- Anotación
- Vistas
Scala puede inferir tipos por uso. Esto hace que la mayoría de las declaraciones de tipos estáticos sean opcionales. No es necesario declarar explícitamente los tipos estáticos a menos que un error del compilador indique la necesidad. En la práctica, se incluyen algunas declaraciones de tipos estáticos para mayor claridad del código.
Enriquecimiento de tipos
Una técnica común en Scala, conocida como "enriquecer mi biblioteca" [39] (originalmente denominada " enriquecer mi biblioteca " por Martin Odersky en 2006; [32] se plantearon inquietudes sobre esta frase debido a sus connotaciones negativas [40] e inmadurez [41] ), permite que se utilicen nuevos métodos como si se agregaran a tipos existentes. Esto es similar al concepto de C# de métodos de extensión pero más poderoso, porque la técnica no se limita a agregar métodos y puede, por ejemplo, usarse para implementar nuevas interfaces. En Scala, esta técnica implica declarar una conversión implícita del tipo que "recibe" el método a un nuevo tipo (típicamente, una clase) que envuelve el tipo original y proporciona el método adicional. Si no se puede encontrar un método para un tipo dado, el compilador busca automáticamente cualquier conversión implícita aplicable a tipos que proporcionen el método en cuestión.
Esta técnica permite agregar nuevos métodos a una clase existente usando una biblioteca complementaria, de modo que solo el código que importa la biblioteca complementaria obtiene la nueva funcionalidad y el resto del código no se ve afectado.
El siguiente ejemplo muestra el enriquecimiento del tipo Intcon los métodos isEveny isOdd:
objeto MyExtensions : extension ( i : Int ) def isEven = i % 2 == 0 def isOdd = ! isEven
import MyExtensions . _ // trae enriquecimiento implícito al alcance 4 . isEven // -> true
La importación de los miembros de MyExtensionslleva la conversión implícita a la clase de extensión IntPredicatesdentro del alcance. [42]
Concurrencia
La biblioteca estándar de Scala incluye soporte para futuros y promesas , además de las API de concurrencia estándar de Java. Originalmente, también incluía soporte para el modelo de actor , que ahora está disponible como una plataforma de código fuente independiente Akka [43] con licencia de Lightbend Inc. Los actores de Akka pueden distribuirse o combinarse con memoria transaccional de software ( transactores ). Las implementaciones alternativas de procesos secuenciales de comunicación (CSP) para el paso de mensajes basado en canales son Communicating Scala Objects, [44] o simplemente a través de JCSP .
Un actor es como una instancia de hilo con un buzón de correo. Se puede crear system.actorOfanulando el receivemétodo para recibir mensajes y utilizando el !método (signo de exclamación) para enviar un mensaje. [45]
El siguiente ejemplo muestra un EchoServer que puede recibir mensajes y luego imprimirlos.
val echoServer = actor ( new Act : become : case msg => println ( "echo " + msg ) )
echoServer ! "hola"
Scala también viene con soporte integrado para programación paralela de datos en forma de Colecciones Paralelas [46] integradas en su Biblioteca Estándar desde la versión 2.9.0.
El siguiente ejemplo muestra cómo utilizar colecciones paralelas para mejorar el rendimiento. [47]
val urls = Lista ( "https://scala-lang.org" , "https://github.com/scala/scala" )
def fromURL ( url : String ) = scala.io.Source.fromURL ( url ) .getLines ( ) . mkString ( " \ n " )
val t = System . currentTimeMillis () urls . par . map ( fromURL ( _ )) // par devuelve la implementación paralela de una colección println ( "time: " + ( System . currentTimeMillis - t ) + "ms" )
Además de futuros y promesas, soporte de actores y paralelismo de datos , Scala también admite programación asincrónica con memoria transaccional de software y flujos de eventos. [48]
Computación en clúster
La solución de computación en clúster de código abierto más conocida escrita en Scala es Apache Spark . Además, Apache Kafka , la cola de mensajes de publicación y suscripción popular con Spark y otras tecnologías de procesamiento de flujo, está escrita en Scala.
Pruebas
Existen varias formas de probar código en Scala. ScalaTest admite múltiples estilos de prueba y puede integrarse con marcos de prueba basados en Java. [49] ScalaCheck es una biblioteca similar a QuickCheck de Haskell . [50] specs2 es una biblioteca para escribir especificaciones de software ejecutables. [51] ScalaMock proporciona soporte para probar funciones de orden superior y currificadas. [52] JUnit y TestNG son marcos de prueba populares escritos en Java.
Versiones
Comparación con otros lenguajes JVM
Scala se compara a menudo con Groovy y Clojure , otros dos lenguajes de programación que también utilizan la JVM. Existen diferencias sustanciales entre estos lenguajes en el sistema de tipos, en el grado en que cada lenguaje admite la programación funcional y orientada a objetos, y en la similitud de su sintaxis con la de Java.
Scala es de tipado estático , mientras que tanto Groovy como Clojure son de tipado dinámico . Esto hace que el sistema de tipos sea más complejo y difícil de entender, pero permite que casi todos los [38] errores de tipo se detecten en tiempo de compilación y puede dar como resultado una ejecución significativamente más rápida. Por el contrario, el tipado dinámico requiere más pruebas para garantizar la corrección del programa y, por lo tanto, generalmente es más lento, para permitir una mayor flexibilidad y simplicidad de programación. Con respecto a las diferencias de velocidad, las versiones actuales de Groovy y Clojure permiten anotaciones de tipo opcionales para ayudar a los programas a evitar la sobrecarga del tipado dinámico en casos en los que los tipos son prácticamente estáticos. Esta sobrecarga se reduce aún más cuando se utilizan versiones recientes de la JVM, que se ha mejorado con una instrucción de invocación dinámica para métodos que se definen con argumentos de tipado dinámico. Estos avances reducen la brecha de velocidad entre el tipado estático y dinámico, aunque un lenguaje de tipado estático, como Scala, sigue siendo la opción preferida cuando la eficiencia de ejecución es muy importante.
En cuanto a los paradigmas de programación, Scala hereda el modelo orientado a objetos de Java y lo extiende de varias maneras. Groovy, aunque también está fuertemente orientado a objetos, se centra más en reducir la verbosidad. En Clojure, se le resta importancia a la programación orientada a objetos y la programación funcional es la principal fortaleza del lenguaje. Scala también tiene muchas facilidades de programación funcional, incluidas características que se encuentran en lenguajes funcionales avanzados como Haskell, e intenta ser agnóstico entre los dos paradigmas, lo que permite al desarrollador elegir entre los dos paradigmas o, más frecuentemente, alguna combinación de ellos.
En cuanto a la similitud sintáctica con Java, Scala hereda gran parte de la sintaxis de Java, al igual que Groovy. Clojure, por su parte, sigue la sintaxis de Lisp , que es diferente tanto en apariencia como en filosofía. [ cita requerida ]
Adopción
Clasificación de idiomas
En 2013, cuando Scala estaba en la versión 2.10, el ThoughtWorks Technology Radar, que es un informe bianual basado en opiniones de un grupo de tecnólogos de alto nivel, [139] recomendó la adopción de Scala en su categoría de lenguajes y marcos de trabajo. [140]
En julio de 2014, esta evaluación se hizo más específica y ahora se refiere a “Scala, las partes buenas”, que se describe como “Para usar Scala con éxito, debe investigar el lenguaje y tener una opinión muy sólida sobre qué partes son adecuadas para usted, creando su propia definición de Scala, las partes buenas”. [141]
En la edición de 2018 de la encuesta State of Java , [142] que recopiló datos de 5160 desarrolladores sobre varios temas relacionados con Java, Scala ocupa el tercer lugar en términos de uso de lenguajes alternativos en la JVM . En relación con la edición del año anterior de la encuesta, el uso de Scala entre los lenguajes alternativos de la JVM cayó del 28,4% al 21,5%, superado por Kotlin , que aumentó del 11,4% en 2017 al 28,8% en 2018. El Índice de popularidad de lenguajes de programación, [143] que rastrea las búsquedas de tutoriales de lenguajes, clasificó a Scala en el puesto 15 en abril de 2018 con una pequeña tendencia a la baja, y en el puesto 17 en enero de 2021. Esto convierte a Scala en el tercer lenguaje basado en JVM más popular después de Java y Kotlin , que ocupa el puesto 12.
En enero de 2021, el ranking de lenguajes de programación RedMonk, que establece clasificaciones basadas en la cantidad de proyectos de GitHub y preguntas realizadas en Stack Overflow , clasificó a Scala en el puesto 14. [144] Aquí , Scala se colocó dentro de un grupo de lenguajes de segundo nivel, por delante de Go , PowerShell y Haskell, y detrás de Swift , Objective-C , Typescript y R.
El índice TIOBE [145] de popularidad de lenguajes de programación emplea clasificaciones de motores de búsqueda de Internet y recuentos de publicaciones similares para determinar la popularidad de los lenguajes. En septiembre de 2021, mostró a Scala en el puesto 31. En esta clasificación, Scala estaba por delante de Haskell (38.º) y Erlang , pero por debajo de Go (14.º), Swift (15.º) y Perl (19.º).
A partir de 2022 [update], los lenguajes basados en JVM como Clojure, Groovy y Scala ocupan puestos altos, pero siguen siendo significativamente menos populares que el lenguaje Java original , que suele situarse entre los tres primeros lugares. [144] [145]
Empresas
- En abril de 2009, Twitter anunció que había cambiado grandes partes de su backend de Ruby a Scala y tenía la intención de convertir el resto. [146]
- Tesla, Inc. utiliza Akka con Scala en el backend de la central eléctrica virtual de Tesla. De este modo, el modelo de actor se utiliza para representar y operar dispositivos que, junto con otros componentes, forman una instancia de la central eléctrica virtual, y los flujos reactivos se utilizan para la recopilación y el procesamiento de datos. [147]
- Apache Kafka está implementado en Scala en lo que respecta a la mayor parte de su núcleo y otras partes críticas. Se mantiene y se extiende a través del proyecto de código abierto y por la empresa Confluent. [148]
- Gilt utiliza Scala y Play Framework . [149]
- Foursquare utiliza Scala y Lift . [150]
- Coursera utiliza Scala y Play Framework . [151]
- Apple Inc. utiliza Scala en ciertos equipos, junto con Java y el marco Play. [152] [153]
- El sitio web de alto tráfico del periódico The Guardian , guardian.co.uk [154], anunció en abril de 2011 que cambiaría de Java a Scala. [155] [156]
- El New York Times reveló en 2014 que su sistema de gestión de contenido interno Blackbeard está construido utilizando Scala, Akka y Play. [157]
- El periódico Huffington Post comenzó a utilizar Scala como parte de su sistema de distribución de contenidos Athena en 2013. [158]
- El banco suizo UBS aprobó Scala para uso en producción general. [159]
- LinkedIn utiliza el microframework Scalatra para potenciar su API Signal. [160]
- Meetup utiliza el kit de herramientas Unfiltered para API en tiempo real. [161]
- Remember the Milk utiliza el kit de herramientas Unfiltered, Scala y Akka para API pública y actualizaciones en tiempo real. [162]
- Verizon busca crear "un marco de próxima generación" utilizando Scala. [163]
- Airbnb desarrolla un software de aprendizaje automático de código abierto llamado “Aerosolve”, escrito en Java y Scala. [164]
- Zalando trasladó su pila tecnológica de Java a Scala y Play. [165]
- SoundCloud utiliza Scala para su back-end, empleando tecnologías como Finagle (microservicios), [166] Scalding y Spark (procesamiento de datos). [167]
- Databricks utiliza Scala para la plataforma Apache Spark Big Data.
- Morgan Stanley utiliza Scala ampliamente en sus proyectos financieros y relacionados con activos. [168]
- Hay equipos dentro de Google y Alphabet Inc. que utilizan Scala, principalmente debido a adquisiciones como Firebase [169] y Nest. [170]
- Walmart Canadá utiliza Scala para su plataforma back-end. [171]
- Duolingo utiliza Scala para su módulo back-end que genera lecciones. [172]
- HMRC utiliza Scala para muchas aplicaciones fiscales del Gobierno del Reino Unido. [173]
- M1 Finance utiliza Scala para su plataforma back-end. [174]
Crítica
En noviembre de 2011, Yammer se alejó de Scala por razones que incluían la curva de aprendizaje para los nuevos miembros del equipo y la incompatibilidad de una versión del compilador de Scala con la siguiente. [175] En marzo de 2015, el ex vicepresidente del grupo de Ingeniería de Plataformas en Twitter, Raffi Krikorian , declaró que no habría elegido Scala en 2011 debido a su curva de aprendizaje . [176] El mismo mes, el vicepresidente sénior de LinkedIn, Kevin Scott, declaró su decisión de "minimizar [su] dependencia de Scala". [177]
Véase también
- sbt , una herramienta de compilación ampliamente utilizada para proyectos de Scala
- Spark Framework está diseñado para manejar y procesar grandes cantidades de datos y es compatible únicamente con Scala.
- Neo4j es un marco de trabajo de Java Spring compatible con Scala con funcionalidad específica del dominio, capacidades analíticas, algoritmos gráficos y mucho más.
- Play!, un marco de aplicación web de código abierto compatible con Scala
- Akka , un conjunto de herramientas de código abierto para crear aplicaciones simultáneas y distribuidas
- Chisel , un lenguaje de código abierto creado en Scala que se utiliza para el diseño y la generación de hardware. [178]
Referencias
- ^ https://www.scala-lang.org/download/3.5.0.html.
{{cite web}}: Falta o está vacío|title=( ayuda ) - ^ "Archivo de aviso". GitHub . 2019-01-24 . Consultado el 2019-12-04 .
- ^ "Macros de Scala".
- ^ Fogus, Michael (6 de agosto de 2010). "MartinOdersky lleva(5) a la lista". Enviar más paramédicos . Consultado el 9 de febrero de 2012 .
- ^ abcd Odersky, Martin (11 de enero de 2006). "El experimento Scala: ¿podemos proporcionar un mejor soporte de lenguaje para sistemas de componentes?" (PDF) . Consultado el 22 de junio de 2016 .
- ^ abcd Odersky, Martín; et al. (2006). "Una descripción general del lenguaje de programación Scala" (PDF) (2ª ed.). Escuela Politécnica Federal de Lausana (EPFL). Archivado (PDF) desde el original el 9 de julio de 2020.
- ^ Odersky, Martin (2008). Programación en Scala. Mountain View, California: Artima. pág. 3. ISBN 9780981531601. Recuperado el 12 de junio de 2014 .
- ^ Wampler, Dean; Payne, Alex (15 de septiembre de 2009). Programación en Scala: escalabilidad = programación funcional + objetos. O'Reilly Media, Inc., pág. 7. ISBN 978-1-4493-7926-1. Consultado el 13 de mayo de 2024.
Los creadores de Scala lo pronuncian scah-lah , como la palabra italiana para "escaleras". Las dos "a" se pronuncian igual.
- ^ Potvin, Pascal; Bonja, Mario (24 de septiembre de 2015). SDL 2013: Model-Driven Dependability Engineering . Apuntes de clase en informática. Vol. 7916. arXiv : 1509.07326 . doi :10.1007/978-3-642-38911-5. ISBN. 978-3-642-38910-8. Número de identificación del sujeto 1214469.
- ^ "Preguntas frecuentes: interoperabilidad con Java". Scala-lang.org . Consultado el 6 de febrero de 2015 .
- ^ Martin Odersky (17 de junio de 2020). Martin Odersky: A Scala 3 Update (video). YouTube. El evento ocurre en 36:35–45:08. Archivado desde el original el 2021-12-21 . Consultado el 2021-04-24 .
- ^ "Efecto expt". scala . Consultado el 31 de julio de 2022 .
- ^ Loverdo, Christos (2010). Pasos en Scala: Introducción a la programación funcional de objetos. Cambridge University Press . p. xiii. ISBN 9781139490948. Recuperado el 31 de julio de 2014 .
- ^ abcd Odersky, Martin (9 de junio de 2006). "Una breve historia de Scala". Artima.com .
- ^ abcd Odersky, M.; Rompf, T. (2014). "Unificando la programación funcional y orientada a objetos con Scala". Comunicaciones de la ACM . 57 (4): 76. doi : 10.1145/2591013 .
- ^ Martin Odersky, "La especificación del lenguaje Scala versión 2.7"
- ^ "El equipo de Scala gana una subvención del ERC" . Consultado el 4 de julio de 2015 .
- ^ "Soporte comercial para Scala". 12 de mayo de 2011. Consultado el 18 de agosto de 2011 .
- ^ "Por qué invertimos en Typesafe: las aplicaciones modernas exigen herramientas modernas". 2011-05-12 . Consultado el 2018-05-08 .
- ^ "Scala de código abierto obtiene respaldo comercial". 2011-05-12 . Consultado el 2011-10-09 .
- ^ "El pionero de la computación en la nube Martin Odersky presenta su nueva empresa Typesafe". 2011-05-12 . Consultado el 2011-08-24 .
- ^ "Scala en Android". Archivado desde el original el 20 de junio de 2016 . Consultado el 8 de junio de 2016 .
- ^ "¡Scala 2.12.8 ya está disponible!". 2018-12-04 . Consultado el 2018-12-09 .
- ^ "Scala Js ya no es experimental | El lenguaje de programación Scala". Scala-lang.org . Consultado el 28 de octubre de 2015 .
- ^ "Lanzamientos · scala-js/Scala-js". GitHub .
- ^ Krill, Paul (15 de marzo de 2017). "La variante de Scala reducida corta los lazos con la JVM". InfoWorld . Consultado el 21 de marzo de 2017 .
- ^ Krill, Paul (11 de mayo de 2016). "El lenguaje Scala se acerca al hardware básico". InfoWorld .
- ^ Se eliminó el backend de .net. por paulp · Solicitud de incorporación de cambios n.° 1718 · scala/scala · GitHub. Github.com (5 de diciembre de 2012). Consultado el 2 de noviembre de 2013.
- ^ "Introducción a Scala". Scala-lang.org . 15 de julio de 2008. Consultado el 31 de julio de 2014 .
- ^ "Inicio". Blog.lostlake.org. Archivado desde el original el 31 de agosto de 2010. Consultado el 25 de junio de 2013 .
- ^ Las estructuras de control integradas de Scala, como
ifowhileno se pueden volver a implementar. Existe un proyecto de investigación, Scala-Virtualized, cuyo objetivo era eliminar estas restricciones: Adriaan Moors, Tiark Rompf, Philipp Haller y Martin Odersky. Scala-Virtualized. Actas del taller ACM SIGPLAN 2012 sobre evaluación parcial y manipulación de programas , 117–120. Julio de 2012. - ^ ab "Pimp my Library". Artima.com. 2006-10-09 . Consultado el 2013-06-25 .
- ^ "Expresiones | Scala 2.13". scala-lang.org . Consultado el 24 de mayo de 2021 .
- ^ "Colecciones mutables e inmutables - Documentación de Scala" . Consultado el 30 de abril de 2020 .
- ^ "Colecciones - Clases de colecciones concretas inmutables - Documentación de Scala" . Consultado el 4 de julio de 2015 .
- ^ Dougherty, Rich. «El blog de Rich Dougherty» . Consultado el 4 de julio de 2015 .
- ^ "TailCalls - API de la biblioteca estándar de Scala (Scaladoc) 2.10.2 - scala.util.control.TailCalls". Scala-lang.org . Consultado el 25 de junio de 2013 .
- ^ ab "Los sistemas de tipos de Java y Scala son incorrectos" (PDF) .
- ^ Giarrusso, Paolo G. (2013). "Reify your collection queries for modularity and speed!". Actas de la 12.ª conferencia internacional anual sobre desarrollo de software orientado a aspectos . ACM. arXiv : 1210.6284 . Bibcode :2012arXiv1210.6284G.
También conocido como patrón pimp-my-library
- ^ Gilbert, Clint (15 de noviembre de 2011). "¿Cuál es la máxima prioridad para que Scala tenga éxito en el mundo corporativo (¿debería estar en el debate de Scala?)?". Scala-lang.org . Consultado el 8 de mayo de 2019 .
- ^ "¿Deberíamos "enriquecer" o "mejorar" las bibliotecas de Scala?". stackexchange.com . 17 de junio de 2013 . Consultado el 15 de abril de 2016 .
- ^ Las clases implícitas se introdujeron en Scala 2.10 para que las extensiones de métodos fueran más concisas. Esto es equivalente a agregar un método
implicit def IntPredicate(i: Int) = new IntPredicate(i). La clase también se puede definir comoimplicit class IntPredicates(val i: Int) extends AnyVal { ... }, lo que produce una denominada clase de valor , también introducida en Scala 2.10. El compilador eliminará entonces las instancias reales y generará métodos estáticos en su lugar, lo que permitirá que los métodos de extensión prácticamente no tengan sobrecarga de rendimiento. - ^ ¿ Qué es Akka?, documentación en línea de Akka
- ^ Sufrin, Bernard (2008). "Comunicación de objetos de Scala". En Welch, PH; Stepney, S.; Polack, FAC; Barnes, FRM; McEwan, AA; Stiles, GS; Broenink, JF; Sampson, AT (eds.). Comunicación de arquitecturas de procesos 2008: WoTUG-31 (PDF) . IOS Press. ISBN 978-1586039073.
- ^ Yan, Kay. "Scala Tour" . Consultado el 4 de julio de 2015 .
- ^ "Parallelcollections - Descripción general - Documentación de Scala". Docs.scala-lang.org . Consultado el 25 de junio de 2013 .
- ^ Yan, Kay. "Scala Tour" . Consultado el 4 de julio de 2015 .
- ^ Aprendiendo programación concurrente en Scala, Aleksandar Prokopec, Packt Publishing
- ^ Kops, Micha (13 de enero de 2013). "Una breve introducción a ScalaTest". hascode.com . Consultado el 7 de noviembre de 2014 .
- ^ Nilsson, Rickard (17 de noviembre de 2008). «ScalaCheck 1.5». Scala-lang.org . Consultado el 7 de noviembre de 2014 .
- ^ "Build web applications using Scala and the Play Framework". workwithplay.com. 2013-05-22. Retrieved 2014-11-07.
- ^ Butcher, Paul (2012-06-04). "ScalaMock 3.0 Preview Release". paulbutcher.com. Archived from the original on 2014-11-08. Retrieved 2014-11-07.
- ^ a b c d e f g "Scala Change History". Scala-lang.org. Archived from the original on 2007-10-09.
- ^ "Dropped: XML Literals". dotty.epfl.ch. Retrieved 2021-03-05.
- ^ "Changes in Version 2.0 (12-Mar-2006)". Scala-lang.org. 2006-03-12. Retrieved 2014-11-07.
- ^ "Changes in Version 2.1.8 (23-Aug-2006)". Scala-lang.org. 2006-08-23. Retrieved 2014-11-07.
- ^ "Changes in Version 2.3.0 (23-Nov-2006)". Scala-lang.org. 2006-11-23. Retrieved 2014-11-07.
- ^ "Changes in Version 2.4.0 (09-Mar-2007)". Scala-lang.org. 2007-03-09. Retrieved 2014-11-07.
- ^ "Changes in Version 2.5 (02-May-2007)". Scala-lang.org. 2007-05-02. Retrieved 2014-11-07.
- ^ "Changes in Version 2.6 (27-Jul-2007)". Scala-lang.org. 2007-06-27. Retrieved 2014-11-07.
- ^ "Changes in Version 2.7.0 (07-Feb-2008)". Scala-lang.org. 2008-02-07. Retrieved 2014-11-07.
- ^ "Changes in Version 2.8.0 (14-Jul-2010)". Scala-lang.org. 2010-07-10. Retrieved 2014-11-07.
- ^ "Changes in Version 2.9.0 (12-May-2011)". Scala-lang.org. 2011-05-12. Retrieved 2014-11-07.
- ^ "Changes in Version 2.10.0". Scala-lang.org. 2013-01-04. Retrieved 2014-11-07.
- ^ Harrah, Mark. "Value Classes and Universal Traits". Scala-lang.org. Retrieved 2014-11-07.
- ^ Suereth, Josh. "SIP-13 - Implicit classes". Scala-lang.org. Archived from the original on 2014-11-08. Retrieved 2014-11-07.
- ^ Suereth, Josh. "String Interpolation". Scala-lang.org. Retrieved 2014-11-07.
- ^ Haller, Philipp; Prokopec, Aleksandar. "Futures and Promises". Scala-lang.org. Retrieved 2014-11-07.
- ^ "SIP-17 - Type Dynamic". Scala-lang.org. Archived from the original on 2014-11-08. Retrieved 2014-11-07.
- ^ "SIP-18 - Modularizing Language Features". Scala-lang.org. Archived from the original on 2014-11-08. Retrieved 2014-11-07.
- ^ Prokopec, Aleksandar; Miller, Heather. "Parallel Collections". Scala-lang.org. Retrieved 2014-11-07.
- ^ Miller, Heather; Burmako, Eugene. "Reflection Overview". Scala-lang.org. Retrieved 2014-11-07.
- ^ Burmako, Eugene. "Def Macros". Scala-lang.org. Retrieved 2014-11-07.
- ^ "Scala 2.10.2 is now available!". Scala-lang.org. 2013-06-06. Archived from the original on 2014-11-08. Retrieved 2014-11-07.
- ^ "Scala 2.10.3 is now available!". Scala-lang.org. 2013-10-01. Archived from the original on 2014-11-08. Retrieved 2014-11-07.
- ^ "Scala 2.10.4 is now available!". Scala-lang.org. 2014-03-18. Retrieved 2015-01-07.
- ^ "Scala 2.10.5 is now available!". Scala-lang.org. 2015-03-04. Retrieved 2015-03-23.
- ^ "Scala 2.11.0 is now available!". Scala-lang.org. 2014-04-21. Retrieved 2014-11-07.
- ^ "Scala 2.11.1 is now available!". Scala-lang.org. 2014-05-20. Retrieved 2014-11-07.
- ^ "Scala 2.11.2 is now available!". Scala-lang.org. 2014-07-22. Retrieved 2014-11-07.
- ^ "Scala 2.11.4 is now available!". Scala-lang.org. 2014-10-30. Retrieved 2014-11-07.
- ^ "Scala 2.11.5 is now available!". Scala-lang.org. 2015-01-08. Retrieved 2015-01-22.
- ^ "¡Scala 2.11.6 ya está disponible!". Scala-lang.org . 2015-03-05 . Consultado el 2015-03-12 .
- ^ "¡Scala 2.11.7 ya está disponible!". Scala-lang.org . 2015-06-23 . Consultado el 2015-07-03 .
- ^ "¡Scala 2.11.8 ya está disponible!". Scala-lang.org . 2016-03-08 . Consultado el 2016-03-09 .
- ^ ab "¡Tres nuevos lanzamientos y más novedades de GitHub!". Scala-lang.org . 2017-04-18 . Consultado el 2017-04-19 .
- ^ "Actualización de seguridad: 2.12.4, 2.11.12, 2.10.7 (CVE-2017-15288)". Scala-lang.org . 2017-11-13 . Consultado el 2018-05-04 .
- ^ "¡Scala 2.12.0 ya está disponible!". Scala-lang.org . 2016-11-03 . Consultado el 2017-01-08 .
- ^ "¡Scala 2.12.1 ya está disponible!". Scala-lang.org . 2016-12-05 . Consultado el 2017-01-08 .
- ^ "¡Scala 2.12.3 ya está disponible!". Scala-lang.org . 2017-07-26 . Consultado el 2017-08-16 .
- ^ "¡Scala 2.12.4 ya está disponible!". Scala-lang.org . 2017-10-18 . Consultado el 2017-10-26 .
- ^ "¡Scala 2.12.5 ya está disponible!". Scala-lang.org . 2018-03-15 . Consultado el 2018-03-20 .
- ^ "¡Scala 2.12.6 ya está disponible!". Scala-lang.org . 2018-04-27 . Consultado el 2018-05-04 .
- ^ "¡Scala 2.12.7 ya está disponible!". Scala-lang.org . 2018-09-27 . Consultado el 2018-10-09 .
- ^ "¡Scala 2.12.8 ya está disponible!". Scala-lang.org . 2018-12-04 . Consultado el 2018-12-09 .
- ^ "¡Scala 2.12.9 ya está disponible!". Scala-lang.org . 2019-08-05 . Consultado el 2021-01-20 .
- ^ "¡Scala 2.12.10 ya está disponible!". Scala-lang.org . 2019-09-10 . Consultado el 2021-01-20 .
- ^ "¡Scala 2.12.11 ya está disponible!". Scala-lang.org . 2020-03-16 . Consultado el 2021-01-20 .
- ^ "¡Scala 2.12.12 ya está disponible!". Scala-lang.org . 2020-07-13 . Consultado el 2021-01-20 .
- ^ "¡Scala 2.12.13 ya está disponible!". Scala-lang.org . 2021-01-12 . Consultado el 2021-01-20 .
- ^ "¡Scala 2.12.14 ya está disponible!". Scala-lang.org . 2021-05-28 . Consultado el 2022-04-15 .
- ^ "¡Scala 2.12.15 ya está disponible!". Scala-lang.org . 2021-09-14 . Consultado el 2022-06-19 .
- ^ "¡Scala 2.12.16 ya está disponible!". Scala-lang.org . 2022-06-10 . Consultado el 2022-06-19 .
- ^ "¡Scala 2.12.17 ya está disponible!". Scala-lang.org . 2022-06-10 . Consultado el 2022-09-16 .
- ^ "¡Scala 2.12.18 ya está disponible!". Scala-lang.org . 2022-06-10 . Consultado el 2023-06-07 .
- ^ "¡Scala 2.12.19 ya está disponible!". Scala-lang.org . 2024-02-25 . Consultado el 2024-08-12 .
- ^ "¡Scala 2.13.0 ya está disponible!". Scala-lang.org . 2019-06-11 . Consultado el 2018-06-17 .
- ^ "¡Scala 2.13.1 ya está disponible!". Scala-lang.org . 2019-09-18 . Consultado el 2021-01-20 .
- ^ "¡Scala 2.13.2 ya está disponible!". Scala-lang.org . 2020-04-22 . Consultado el 2021-01-20 .
- ^ "¡Scala 2.13.3 ya está disponible!". Scala-lang.org . 2020-06-25 . Consultado el 2021-01-20 .
- ^ "¡Scala 2.13.4 ya está disponible!". Scala-lang.org . 2020-11-19 . Consultado el 2021-01-20 .
- ^ "¡Scala 2.13.5 ya está disponible!". Scala-lang.org . 2021-02-22 . Consultado el 2021-02-26 .
- ^ "¡Scala 2.13.6 ya está disponible!". Scala-lang.org . 2021-05-17 . Consultado el 2022-04-15 .
- ^ "¡Scala 2.13.7 ya está disponible!". Scala-lang.org . 2021-11-01 . Consultado el 2022-04-15 .
- ^ "¡Scala 2.13.8 ya está disponible!". Scala-lang.org . 2022-01-12 . Consultado el 2022-04-15 .
- ^ "¡Scala 2.13.9 ya está disponible!". Scala-lang.org . 2022-09-21 . Consultado el 2023-08-28 .
- ^ "¡Scala 2.13.10 ya está disponible!". Scala-lang.org . 2022-10-13 . Consultado el 2023-08-28 .
- ^ "¡Scala 2.13.11 ya está disponible!". Scala-lang.org . 2023-06-07 . Consultado el 2023-08-28 .
- ^ "¡Scala 2.13.12 ya está disponible!". Scala-lang.org . 2023-09-11 . Consultado el 2024-08-12 .
- ^ "¡Scala 2.13.13 ya está disponible!". Scala-lang.org . 2024-02-26 . Consultado el 2024-08-12 .
- ^ "¡Scala 2.13.14 ya está disponible!". Scala-lang.org . 2024-05-01 . Consultado el 2024-08-12 .
- ^ "¡Scala 3 ya está aquí!". Scala-lang.org . 2021-05-14 . Consultado el 2021-05-26 .
- ^ "¡Scala 3.0.1 y 3.0.2-RC1 ya están aquí!". Scala-lang.org . 2021-07-31 . Consultado el 2024-08-12 .
- ^ "¡Scala 3.0.2 ya está disponible!". Scala-lang.org . 2021-09-07 . Consultado el 2024-08-12 .
- ^ "¡Lanzamiento de Scala 3.1.0!". Scala-lang.org . 2021-10-21 . Consultado el 2024-08-12 .
- ^ "Novedades sobre compatibilidad con versiones posteriores y Scala 3.1.1". Scala-lang.org . 2022-02-01 . Consultado el 2024-08-12 .
- ^ "¡Scala 3.1.2 ya está disponible!". Scala-lang.org . 2022-04-12 . Consultado el 2024-08-12 .
- ^ "¡Scala 3.1.3 ya está disponible!". Scala-lang.org . 2022-06-21 . Consultado el 2024-08-12 .
- ^ "¡Scala 3.2.0 ya está disponible!". Scala-lang.org . 2022-09-05 . Consultado el 2024-08-12 .
- ^ "¡Scala 3.2.1 ya está disponible!". Scala-lang.org . 2022-11-07 . Consultado el 2024-08-12 .
- ^ "¡Scala 3.2.2 ya está disponible!". Scala-lang.org . 2023-01-30 . Consultado el 2024-08-12 .
- ^ "¡Scala 3.3.0 ya está disponible!". Scala-lang.org . 2023-05-30 . Consultado el 2024-08-12 .
- ^ "¡Scala 3.3.1 LTS ya está disponible!". Scala-lang.org . 2023-09-07 . Consultado el 2024-08-12 .
- ^ "Scala 3.3.2". github.com. 2024-02-29. Retrieved 2024-08-12.
- ^ "Scala 3.4.0 and 3.3.3 LTS released!". Scala-lang.org. 2024-02-29. Retrieved 2024-08-12.
- ^ "Scala 3.4.0 and 3.3.3 LTS released!". Scala-lang.org. 2024-02-29. Retrieved 2024-08-12.
- ^ "Scala 3.4.1 is now available!". Scala-lang.org. 2024-03-29. Retrieved 2024-08-12.
- ^ "Scala 3.4.2 is now available!". Scala-lang.org. 2024-05-16. Retrieved 2024-08-12.
- ^ "ThoughtWorks Technology Radar FAQ".
- ^ "ThoughtWorks Technology Radar MAY 2013" (PDF).
- ^ "Scala, the good parts".
- ^ "The State of Java in 2018".
- ^ "Popularity of Programming Language Index".
- ^ a b O'Grady, Stephen (1 March 2021). "The RedMonk Programming Language Rankings: January 2021". RedMonk.
- ^ a b "TIOBE Index for May 2021".
- ^ Greene, Kate (1 April 2009). "The Secret Behind Twitter's Growth, How a new Web programming language is helping the company handle its increasing popularity". Technology Review. MIT. Retrieved 6 April 2009.
- ^ Breck, Colin; Link, Percy (2020-03-23). "Tesla Virtual Power Plant (Architecture and Design)". Retrieved 2023-03-28.
- ^ "Apache Kafka source code at GitHub". Apache Software Foundation. Retrieved 29 March 2023.
- ^ "Play Framework, Akka and Scala at Gilt Groupe". Lightbend. 15 July 2013. Retrieved 16 July 2016.
- ^ "Scala, Lift, and the Future". Archived from the original on 13 January 2016. Retrieved 4 July 2015.
- ^ Saeta, Brennan (2014-02-17). "Why we love Scala at Coursera". Coursera Engineering. Retrieved 2023-09-21.
- ^ "Apple Engineering PM Jarrod Nettles on Twitter". Jarrod Nettles. Retrieved 2016-03-11.
- ^ "30 Scala job openings at Apple". Alvin Alexander. Retrieved 2016-03-11.
- ^ David Reid & Tania Teixeira (26 February 2010). "Are people ready to pay for online news?". BBC. Retrieved 2010-02-28.
- ^ "Guardian switching from Java to Scala". Heise Online. 2011-04-05. Retrieved 2011-04-05.
- ^ "Guardian.co.uk Switching from Java to Scala". InfoQ.com. 2011-04-04. Retrieved 2011-04-05.
- ^ Roy, Suman; Sundaresan, Krishna (2014-05-13). "Building Blackbeard: A Syndication System Powered By Play, Scala and Akka". The New York Times. Retrieved 2014-07-20.
- ^ Pavley, John (2013-08-11). "Sneak Peek: HuffPost Brings Real Time Collaboration to the Newsroom". Huffington Post. Retrieved 2014-07-20.
- ^ Binstock, Andrew (2011-07-14). "Interview with Scala's Martin Odersky". Dr. Dobb's Journal. Retrieved 2012-02-10.
- ^ Synodinos, Dionysios G. (2010-10-11). "LinkedIn Signal: A Case Study for Scala, JRuby and Voldemort". InfoQ.
- ^ "Real-life Meetups Deserve Real-time APIs".
- ^ "Real time updating comes to the Remember The Milk web app".
- ^ "WHAT IS SCALA". 8 March 2023. Retrieved 2023-03-17.
- ^ Novet, Jordan (2015-06-04). "Airbnb announces Aerosolve, an open-source machine learning software package". Retrieved 2016-03-09.
- ^ Kops, Alexander (2015-12-14). "Zalando Tech: From Java to Scala in Less Than Three Months". Retrieved 2016-03-09.
- ^ Calçado, Phil (2014-06-13). "Building Products at SoundCloud—Part III: Microservices in Scala and Finagle". Retrieved 2016-03-09.
- ^ "Customer Case Studies: SoundCloud". Concurrent Inc. 2014-11-18. Retrieved 2016-03-09.
- ^ Scala at Morgan Stanley (video). Skills Matter. 2015-12-03. Retrieved 2016-03-11.
- ^ Greg Soltis (2015-12-03). SF Scala, Greg Soltis: High Performance Services in Scala (video). Skills Matter. Archived from the original on 2021-12-21. Retrieved 2016-03-11.
- ^ Lee Mighdoll. "Scala jobs at Nest". Retrieved 2016-03-11.
- ^ Nurun. "Nurun Launches Redesigned Transactional Platform With Walmart Canada". Retrieved 2013-12-11.
- ^ Horie, André K. (2017-01-31). "Rewriting Duolingo's engine in Scala". Retrieved 2017-02-03.
- ^ "HMRC GitHub repository". GitHub.
- ^ "Meet M1 Finance, A ScalaCon Gold Sponsor". ScalaCon. Retrieved 2023-09-02.
- ^ Hale, Coda (29 November 2011). "The Rest of the Story". codahale.com. Retrieved 7 November 2013.
- ^ Krikorian, Raffi (17 March 2015). O'Reilly Software Architecture Conference 2015 Complete Video Compilation: Re-Architecting on the Fly - Raffi Krikorian - Part 3 (video). O'Reilly Media. Event occurs at 4:57. Retrieved 8 March 2016.
What I would have done differently four years ago is use Java and not used Scala as part of this rewrite. [...] it would take an engineer two months before they're fully productive and writing Scala code.
[permanent dead link] - ^ Scott, Kevin (11 Mar 2015). "Is LinkedIn getting rid of Scala?". quora.com. Retrieved 25 January 2016.
- ^ "Chisel: Constructing Hardware in a Scala Embedded Language". UC Berkeley APSIRE. Retrieved 27 May 2020.
Further reading
- Odersky, Martin; Spoon, Lex; Venners, Bill (15 December 2019). Programming in Scala: A Comprehensive Step-by-step Guide (4th ed.). Artima Inc. p. 896. ISBN 978-0-9815316-1-8.
- Horstmann, Cay (15 December 2016). Scala for the Impatient (2nd ed.). Addison-Wesley Professional. p. 384. ISBN 978-0-134-54056-6.
- Wampler, Dean; Payne, Alex (14 December 2014). Programming Scala: Scalability = Functional Programming + Objects (2nd ed.). O'Reilly Media. p. 583. ISBN 978-1-491-94985-6.
- Suereth, Joshua D. (Spring 2011). Scala in Depth. Manning Publications. p. 225. ISBN 978-1-935182-70-2.
- Meredith, Gregory (2011). Monadic Design Patterns for the Web (PDF) (1st ed.). p. 300.
- Odersky, Martin; Spoon, Lex; Venners, Bill (10 December 2008). Programming in Scala, eBook (1st ed.). Artima Inc.