Nuevo Kotlin User Group en Valencia y event "Estado de Machine Learning en Kotlin"
¡Se acaba de inaugurar el nuevo Kotlin Valencia User Group! Inicialmente organizado por Carlos Cáceres
Nos complace presentaros el cuarto hito de la próxima versión de Kotlin.
Estamos ultimando detalles de la 1.1 y tenemos previsto sacar una versión final
para el primer trimestre de 2017.
La mayoría de las características están ya bastante perfiladas,
así que es un buen momento para que la probéis y nos digáis vuestra opinión.
¡Nos ayudaría mucho!
Como otra versión hito, no ofrecemos ninguna garantía de retrocompatibilidad
en relación a las nuevas características del lenguaje y librerías.
Cualquier cosa que introduzcamos en la 1.1 está sujeto a cambio antes de la versión final.
Por favor, compartid vuestra opinión sobre las nuevas características o cualquier problema
que os surja, via YouTrack, los foros o Slack.
En este hito hemos cambiado sustancialmente la sintaxis de las corrutinas y las semánticas,
haciendéndolas más sencillas y flexibles.
También viene con mejoras en la librería estándar, nuevas características del lenguaje,
plugins de compilación, numerosas características y mejoras en el backend de JavaScript,
así como correcciones y actualizaciones.
La nueva versión también incluye todas las características introducidas en
Kotlin 1.0.6, incluyendo actualizaciones
de compatibilidad con Android Studio 2.3 Beta 1.
Puedes encontrar aquí la lista de cambios completa y vamos a destacar algunos cambios abajo:
Le hemos dado una nueva vuelta de tuerca al diseño de las corrutinas, haciéndola más sencillas, más capacidad de composición y más potentes:
<code class="highlighter-rouge">coroutine
. La corrutina es ahora una mera instancia de una computación suspendible que se inicia con la función <code class="highlighter-rouge">startCoroutine
de la librería estándar.<code class="highlighter-rouge">generate
y <code class="highlighter-rouge">yield
, que construyen secuencias síncronas, limitan las suspensiones dentro de los bloques generate usando la anotación <code class="highlighter-rouge">@RestrictsSuspension
.La función de suspensión clásica <code class="highlighter-rouge">await
se puede implementar ahora mediante una llamada en posición tailcall a la función de suspensión <code class="highlighter-rouge">suspendCoroutine
que es parte de la librería estándar.
suspend fun
El constructor correspondiente se llama <code class="highlighter-rouge">async
y se implementa mediante la función <code class="highlighter-rouge">startCoroutine
:
fun
Y se pueden usar conjuntamente para escribir código más natural con futures:
async { val original = asyncLoadImage("...original...") // creates a Future val overlay = asyncLoadImage("...overlay...") // creates a Future ... // suspend while awaiting the loading of the images // then run applyOverlay(...)
when they are both loaded return applyOverlay(await(original), await(overlay)) }
Sin embargo, los futures son solo uno de los casos de uso de las corrutinas.
Podéis encontrar información detallada junto a implementaciones y ejemplos de uso en el documento KEEP revisado.
Creemos que ahora tenemos un gran diseño de corrutinas para Kotlin, pero somos conscientes de que
no ha sido probado lo suficiente exhaustivamente todavía. De forma que vamos a publicarlo en la 1.1,
con uso opcional bajo un flag de incubación.
A partir de esta versión os aparecerá una advertencia
“This feature is experimental: coroutines” al usar las corrutinas.
Podéis deshabilitar esta advertencia con el flag de compilación <code class="highlighter-rouge">-Xcoroutines=enable
o deshabilitar dicha característica con el flag<code class="highlighter-rouge">-Xcoroutines=error
.
La configuración correspondiente está disponible en las preferencias del compilador de Kotlin en IDEA.
Para setear esta opción en un proyecto gradle podéis añadir <code class="highlighter-rouge">kotlin.coroutines=enable
o <code class="highlighter-rouge">kotlin.coroutines=error
al archivo raíz del proyecto <code class="highlighter-rouge">local.properties
.
Si estáis usando la librería kotlinx.coroutines por favor, usad la versión actualizada <code class="highlighter-rouge">0.2-alpha-1
, adaptada
a los nuevos cambios del diseño de corrutinas. Esta versión también introduce
el método <code class="highlighter-rouge">yieldAll
en el ámbito <code class="highlighter-rouge">generate
. Por favor leed el archivo readme para más detalles.
Por ejemplo, en el código de abajo se inferirá automáticamente el tipo de la propiedad <code class="highlighter-rouge">foo
a <code class="highlighter-rouge">String
.
Ver la tarea KT-550 para más información.
val foo get() = ""
La comparación de números de coma flotante usa ahora una comparación compatible con IEEE 754
cuando el tipo se conoce de forma estática que es <code class="highlighter-rouge">Double
o <code class="highlighter-rouge">Float
.
Para rangos de números de coma flotante hemos introducido una interfaz especializada <code class="highlighter-rouge">ClosedfloatingPointRange
, que proporciona
su propio método de comparación, de forma que las operaciones de extensión como <code class="highlighter-rouge">coerceIn
, se pueden implementar por encima.
Su instancias se obtiene con el operador <code class="highlighter-rouge">..
incoado con dos valores <code class="highlighter-rouge">Float
o <code class="highlighter-rouge">Double
.
Ved KT-4481 y KT-14651 para más detalles.
Ahora es posible interceptar delegados al bindeo de la propiedad usando el operador <code class="highlighter-rouge">provideDelegate
.
Por ejemplo, si queremos comprobar el nombre de la propiedad antes de bindear, podemos hacer algo como esto:
class ResourceLoader
Aquí se llamará al método <code class="highlighter-rouge">provideDelegate
en el inicializador del constructor de la clase <code class="highlighter-rouge">MyUI
.
Así que podemos comprobar la consistencia de las propiedades en el momento de la creación.
En versiones anteriores solo era posible en el momento de llamar al getter o al setter.
Desafortunadamente dicha característica no está documentada apropiadamente todavía, pero podéis ver el
borrador del documento como referencia inicial.
Algunas funciones del JDK tienen un contrato de nulabilidad definido en la documentación,
otros no aceptan valores null, y otros devuelven null a veces.
Desafortunadamente, el JDK no usa ninguna anotación para expresar dichos contratos
y solo proporciona dicha información en la documentación.
Antes de la 1.0 usábamos un artefacto de anotaciones externas para el JDK
que se podía proporcionar por el compilador para alterar las firmas de las funciones del JDK,
pero dicha aproximación no era lo suficiente confiable.
Ahora introducimos una nueva aproximación: embebiendo la información necesaria para mejorar las firmas
del JDK directamente en el compilador. Como primer paso cubrimos la nulabilidad de un pequeño subset del API.
<code class="highlighter-rouge">java.util.Optional
<code class="highlighter-rouge">of
: no permite valores nulos<code class="highlighter-rouge">ofNillable
, toma valores nullable, y devuelve un <code class="highlighter-rouge">Optional
que no puede ser nulable.<code class="highlighter-rouge">get
siempre devuelve un valor no nulo.<code class="highlighter-rouge">java.lang.ref.Reference
y todos sus herederos, como <code class="highlighter-rouge">WeakReference
y <code class="highlighter-rouge">SoftReference
:<code class="highlighter-rouge">get
devuelve un valor nulable,, ya que se puede volver null en cualquier momento si el objeto referenciado es recolectado por el recolector de basura<code class="highlighter-rouge">Iterator
, <code class="highlighter-rouge">Iterable
, <code class="highlighter-rouge">Collection
, <code class="highlighter-rouge">List
, <code class="highlighter-rouge">Map
que se exponen como funciones dependientes de la plataforma en las interfaces de colección intrínsecas de Kotlin.Estas mejoras son seguras en la mayoría de casos. En particular, son seguros cuando los tipos mejorados se hacen más específicos (no nulables) en posiciones de retorno o más generales (nilable) en posiciones de parámetros.
Pero cuando el tipo cambia en la dirección opuesta, ducho cambio puede romper código.
Tratamos de no introducir dichas mejoras que puedan romper códigoa no ser que respeten la nulabilidad correctamente
pudiendo llevar a excepciones en runtime. Así que por ejemplo <code class="highlighter-rouge">Optional.of
ahora recibe un argumento no nulable que es más restrictivo, pero tratar de pasar <code class="highlighter-rouge">null
a dicho método
llevaría a una excepció en runtime en cualquier caso.
Por otro lado, hemos decidido no especificar la nulabilidad correcta para <code class="highlighter-rouge">File.listFiles
que puede devolver null en determinados casos,
porque en la mayoría de los casos no hay una opción mejor que lanzar otra excepción.
<code class="highlighter-rouge">@PublishedApi
. Cuando se aplica en un miembro interno, se convierte a efectos prácticos en pública y está disponible desde la función pública inline. Ver KT-12215 para más información.<code class="highlighter-rouge">const val
ahora se reemplazan inline (ver KT-11734)<code class="highlighter-rouge">mod
para el operador <code class="highlighter-rouge">%
(resto) con algunas consecuencias no muy agradables (ver KT-14650). Por lo que hemos decidido introducir el operador <code class="highlighter-rouge">rem
, y deprecar el <code class="highlighter-rouge">mod
y proporcionar las herramientas para que la transición sea todo lo fácil posible.Hay un buen puñado de extensiones nuevas para la clase String para convertir números sin lanzar excepciones o números invákidos: <code class="highlighter-rouge">String.toIntOrNull(): Int?
, <code class="highlighter-rouge">String.toDoubleOrNull(): Double?
etc.
Tened en cuenta que dichas funciones producirán un boxing de los nñumeros al devolverlos, como asume el tipo de retorno.
También las conversiones de enteros, <code class="highlighter-rouge">Int.toString()
, <code class="highlighter-rouge">String.toInt()
, <code class="highlighter-rouge">String.toIntOrNull()
tienen una nueva sobrecarga con un parámetro <code class="highlighter-rouge">radix
, que permite especificar la base de conversión.
Nos gustaría agradecer a Daniil Vodopian por su contribución sustancial al desarrollo de dichas funciones.
<code class="highlighter-rouge">onEach
es una función de extensión pequeña pero útil para colecciones y secuencias, que permite
realizar alguans acciones, posiblemente con efectos colaterales, en cada elemento de la colección/secuenciaen una operación de la cadena.
En iterables se comporta como <code class="highlighter-rouge">forEach
pero también devuelve una instancia iterable. Y en secuencias devuelve una secuencia wrappeada, que aplica la acción proporcionada de forma vaga conforme se itera sobre los elementos.
Gracias a Christian Brüggemann por su prototipo inicial.
<code class="highlighter-rouge">external
en vez de <code class="highlighter-rouge">@native
Desde esta versión deprecamos la anotación <code class="highlighter-rouge">@native
y en su lugar debes usar el modificador <code class="highlighter-rouge">external
.
A diferencia del target JVM, el de JS permite usar el modificador <code class="highlighter-rouge">external
en clases y propiedades.
Nótese, que no tienes por qué marcar los miembros como <code class="highlighter-rouge">external
en clases que ya tienen el modificador <code class="highlighter-rouge">external
, ya que se hereda automáticamente. Así que en vez de:
@native fun alert(message: Any?): Unit {}
podéis escribir
external fun alert(message: Any?)
Ahora podéis describir las declaraciones que se tienen que importar de los módulos de JavaScript de forma más precisa.
Si añadís la anotación <code class="highlighter-rouge">@JsModule("<module-name>")
en una declaración externa,
se importará de forma adecuada al sistema de módulos (ya sea CommonJS o AMD) durante la compilación. Por ejemplo, con CommonJS la declaración se importará via la función <code class="highlighter-rouge">require(...)
.
Adicionalmente, si queréis importar una declaración bien com módulo o como objeto global de JavaScript, podéis usar la anotación <code class="highlighter-rouge">@JsNonModule
.
Veamos un ejemplo completo. Podéis importar la librería jQuery a código Kotlin así:
@JsModule("jquery") @JsNonModule @JsName("$") external abstract class JQuery { fun toggle(duration: Int = 0): JQuery fun click(handler: (Event) -> Unit): JQuery } @JsModule("jquery") @JsNonModule @JsName("$") external fun JQuery(selector: String): JQuery
En este caso, se importará JQuery como módulo llamado <code class="highlighter-rouge">jquery
y alternativamente, se puede usar un objeto <code class="highlighter-rouge">$
,
dependiendo de qué sistema de módulos se configure para usar en el compilador de Kotlin.
Podéis usar dichas declaraciones en vuestra aplicación así:
fun main(args: Array
Podéis comprobar el código JS generado a para CommonJS y sistemas de módulos planos aquí.
En Maven/Gradle: Añadir http://dl.bintray.com/kotlin/kotlin-eap-1.1 como repositorio para el build script en vuestros proyectos; y usar 1.1-M04 como el nñumero de versión para el compilador y la librería estándar.
En IntelliJ IDEA: Ir a Tools -> Kotlin -> Configure Kotlin Plugin Updates, y selecionar “Early Access Preview 1.1” en el desplegable Update channel y pulsad sobre Check for updates.
El compilador de línea de comandos se puede descargar de la página de releases de Github.
En try.kotlinlang.org Usad el desplegable de la esquina inferior derecha para cambiar la versión del compilador a la 1.1-M04.
¡Feliz Kotlin-dad!