tutorial software fungicida examples blanquerna scala

software - scala vs java



¿Cuáles son las principales diferencias entre Scala 2.8 y Scala 2.7? (5)

He escrito un programa bastante grande en Scala 2.7.5, y ahora estoy esperando la versión 2.8. Pero tengo curiosidad sobre cómo este gran salto en la evolución de Scala me afectará.

¿Cuáles serán las principales diferencias entre estas dos versiones de Scala? Y quizás lo más importante:

  • ¿Tendré que volver a escribir algo?
  • ¿ Quiero volver a escribir algo solo para aprovechar una nueva función genial?
  • ¿Cuáles son exactamente las nuevas características de Scala 2.8 en general?

¿Tendré que volver a escribir algo?

def takesArray(arr: Array[AnyRef]) {…} def usesVarArgs(obs: AnyRef*) { takesArray(obs) }

necesita convertirse

def usesVarArgs(obs: AnyRef*) { takesArray(obs.toArray) }

Tuve que visitar el canal de IRC para eso, pero luego me di cuenta de que debería haber empezado aquí.


Tomando el salto

Cuando migra, el compilador puede proporcionarle algunas redes de seguridad.

  1. Compila tu código anterior contra 2.7.7 con -deprecation , y sigue las recomendaciones de todas las advertencias de deprecation.
  2. Actualice su código para usar paquetes no anulados. Esto se puede hacer mecánicamente ejecutando repetidamente esta búsqueda de expresión regular.

    s/^(package com.example.project.*)/.(/w+)/$1/npackage $2/g

  3. Compilar con el compilador 2.8.0, usando opciones de línea de comando paranoide -deprecation -Xmigration -Xcheckinit -Xstrict-warnings -Xwarninit

  4. Si recibe errores, el error could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T] , necesita agregar un parámetro implícito (o equivalente, un límite de contexto), en un parámetro de tipo.

    Antes de:

    scala> def listToArray[T](ls: List[T]): Array[T] = ls.toArray <console>:5: error: could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T] def listToArray[T](ls: List[T]): Array[T] = ls.toArray ^

    Después:

    scala> def listToArray[T: Manifest](ls: List[T]): Array[T] = ls.toArray listToArray: [T](ls: List[T])(implicit evidence$1: Manifest[T])Array[T] scala> def listToArray[T](ls: List[T])(implicit m: Manifest[T]): Array[T] = ls.toArray listToArray: [T](ls: List[T])(implicit m: Manifest[T])Array[T]

    Cualquier método que llame a listToArray , y tome T como un parámetro de tipo, también debe aceptar el Manifiesto como un parámetro implícito. Vea el SID de matrices para más detalles.

  5. En poco tiempo, te encontrarás con un error como este:

    scala> collection.Map(1 -> 2): Map[Int, Int] <console>:6: error: type mismatch; found : scala.collection.Map[Int,Int] required: Map[Int,Int] collection.Map(1 -> 2): Map[Int, Int] ^

    Debe comprender que el tipo Map es un alias en Predef para collection.immutable.Map .

    object Predef { type Map[A, B] = collection.immutable.Map[A, B] val Map = collection.immutable.Map }

    Hay tres tipos denominados Map : una interfaz de solo lectura: collection.Map , una implementación inmutable: collection.immutable.Map y una implementación mutable: collection.mutable.Map . Además, la biblioteca define el comportamiento en un conjunto paralelo de rasgos MapLike , pero esto es realmente un detalle de implementación.

Cosechar los beneficios

  1. Reemplace alguna sobrecarga de método con parámetros nombrados y predeterminados.
  2. Use el método de copy generado de las clases de casos.

    scala> case class Foo(a: Int, b: String) defined class Foo scala> Foo(1, "a").copy(b = "b") res1: Foo = Foo(1,b)

  3. Generalice sus firmas de métodos de List a Seq o Iterable o Traversable . Debido a que las clases de colección están en una jerarquía limpia, ¿puede aceptar un tipo más general?
  4. Integrar con las bibliotecas de Java utilizando anotaciones. Ahora puede especificar anotaciones anidadas y tener un control detallado sobre si las anotaciones se dirigen a campos o métodos. Esto ayuda a usar Spring o JPA con el código de Scala.

Hay muchas otras características nuevas que se pueden ignorar de forma segura a medida que comienza a migrar, por ejemplo @specialized y Continuations.


Aquí hay una lista de verificación de Eric Willigers, que ha estado usando Scala desde 2.2. Algunas de estas cosas parecerán anticuadas a los usuarios más recientes.

* Importación explícita de paquetes externos *

Supongamos que tenemos

package a class B

Cambio

package a.c class D extends B

a

package a.c import a.B class D extends B

o

package a package c class D extends B

* Utilice un nombre de paquete completamente calificado al importar desde el paquete externo *

Supongamos que tenemos

package a.b object O { val x = 1 }

Cambio

package a.b.c import b.O.x

a

package a.b.c import a.b.O.x

* Al especificar explícitamente los parámetros de tipo en las llamadas al método contenedor, agregue nuevos parámetros de tipo *

Cambio

list.map[Int](f)

a

list.map[Int, List[Int]](f)

Cambio

map.transform[Value](g)

a

map.transform[Value, Map[Key, Value]](g)

* Crea un mapa ordenado usando Ordering en lugar de la conversión a Ordered *

[scalac] found : (String) => Ordered[String] [scalac] required: Ordering[String] [scalac] TreeMap[String, Any](map.toList: _*)(stringToCaseInsensitiveOrdered _)

* Importar las conversiones implícitas que reemplazan scala.collection.jcl *

* Inmutable Map .update se convierte en .updated *

*** Migrar de métodos de Lista recientemente desaprobados -
* elements * remove * sort * List.flatten(someList) * List.fromString(someList, sep) * List.make

*** Usar métodos de lista * diff * filterNot * sortWith * someList.flatten * someList.split(sep) * someList.split(sep) * List.fill

* classpath al usar scala.tools.nsc.Settings *

http://thread.gmane.org/gmane.comp.lang.scala/18245/focus=18247 settings.classpath.value = System.getProperty ("java.class.path")

* Evitar el error: _ debe seguir el método; no puede seguir (Cualquiera) => Booleano *

Reemplazar

list.filter(that.f _)

con

list.filter(that f _)

o

list.filter(that.f(_))

>>>

* Migrar desde los métodos de enumeración en desuso iterator map * Usar los métodos de enumeración values.iterator values.map

* Migrar desde Iterator.fromValues ​​en desuso Iterator.fromValues(a, b, c, d) * Usar Iterator(a, b, c, d)

* Evitar la recopilación de tipo en desuso * Usar Iterable lugar

* Cambiar orden de inicialización *

Supongamos que tenemos

trait T { val v val w = v + v }

Reemplazar

class C extends T { val v = "v" }

con

class C extends { val v = "v" } with T

* Evite val innecesario for (val x <- ...) *

* Evite las comillas finales *


Aquí puede encontrar una vista previa de la nueva función en Scala2.8 (abril de 2009), completada con un artículo reciente (junio de 2009)

  • Argumentos nombrados y predeterminados
  • Anotaciones anidadas
  • Objetos del paquete
  • @especializado
  • Colecciones mejoradas (algunas reescrituras pueden ser necesarias aquí)
  • REPL tendrá finalización del comando (más sobre eso y otros trucos en este artículo )
  • Nuevas abstracciones de control (continuación o ruptura)
  • Mejoras (Swing wrapper, performances, ...)

El "código de reescritura" no es una obligación (excepto para usar algunas de las Colecciones mejoradas), pero algunas características como la continuation ( Wikipedia : una representación abstracta del estado de control, o el "resto de computación" o "resto de código para ser ejecutado" ") puede darte algunas ideas nuevas. Una buena introducción se encuentra aquí , escrita por Daniel (quien también ha publicado una respuesta mucho más detallada y específica en este hilo).

Nota: Scala en Netbeans parece funcionar con algo de 2.8 nightly-build (frente a la página oficial de 2.7.x )


La respuesta de VonC es difícil de mejorar, así que ni siquiera intentaré hacerlo. Cubriré algunas otras cosas que él no mencionó.

Primero, algunas cosas desaprobadas irán. Si tiene advertencias de desaprobación en su código, es probable que ya no compile.

Luego, la biblioteca de Scala se está expandiendo. Principalmente, pequeños patrones comunes como capturar excepciones en Either u Option , o convertir un AnyRef en una Opción con null mapeado en None . Estas cosas en su mayoría pueden pasar desapercibidas, pero me estoy cansando de publicar algo en el blog y más tarde tener a alguien que me diga que ya está en Scala 2.8. Bueno, en realidad, no me estoy cansando de eso, pero, mejor dicho, y felizmente, solía hacerlo. Y no estoy hablando aquí de las colecciones, que están recibiendo una revisión importante.

Ahora, sería bueno si las personas publicaran ejemplos reales de tales mejoras de la biblioteca como respuestas. Me encantaría volver a votar todas esas respuestas.

REPL no obtiene solo la finalización del comando. Está obteniendo muchas cosas, incluida la capacidad de examinar el AST para un objeto, o la capacidad de insertar puntos de ruptura en el código que cae en REPL.

Además, el compilador de Scala se está modificando para poder proporcionar una compilación parcial rápida a los IDE, lo que significa que podemos esperar que se vuelvan mucho más "conocedores" de Scala, al consultar el código sobre el propio compilador de Scala.

Es probable que un gran cambio pase desapercibido para muchos, aunque reducirá los problemas tanto para los escritores como para los usuarios. En este momento, si escribe lo siguiente:

package com.mystuff.java.wrappers import java.net._

Está importando no la biblioteca de net de Java, pero la biblioteca de net com.mystuff.java , como com , com.mystuff , com.mystuff.java y com.mystuff.java.wrappers todas están dentro del alcance, y java se puede encontrar en el interior com.mystuff . Con Scala 2.8, solo los wrappers se abren. Dado que, a veces, desea que parte del resto esté en Scope, ahora se permite una sintaxis de package alternativa:

package com.mystuff.factories package ligthbulbs

que es equivalente a:

package com.mystuff.factories { package lightbulbs { ... } }

Y pasa a tener tanto factories como lightbulbs en alcance.