domingo, 23 de agosto de 2015

Nulabilidad en #java y en #kotlin


Hoy voy a hablar sobre la nulabilidad en Kotlin.

Un poco de historia:

Como sabemos, tradicionalmente en los lenguajes de programación los tipos de valor no son nullables, mientras que los tipos de referencia sí lo son. Los tipos por referencia, generalmente objetos, tienen su contenido en una zona de memoria y cuando tenemos ese objeto en la pila o lo pasamos a otra función, con lo que estamos trabajando es con una referencia, con un puntero.

Al final un puntero acaba siendo un número que hace referencia a una posición en la memoria.
Y la referencia nula (o puntero a la posición 0) originalmente no tenía ningún significado en especial. Al principio se aprovechaba toda la memoria que era poco y no había memoria virtual ni traducciones de direcciones ni nada de eso.


Al final generalmente cuando algo había ido mal, acabábamos con punteros que hacían referencia a posiciones inválidas o que no queríamos, que muchas veces eran valores bajos que hacían referencia a partes bajas de la memoria. Por ejemplo si hacíamos un "malloc" que fallaba, esto devolvía NULL, un puntero a la posición 0, y si luego accedíamos en un campo, igual estábamos accediendo a la posición de memoria 96 por ejemplo. Lo cual era bastante peliagudo. Pero con arquitecturas sistemas operativos más modernos, esto empezó a suponer violaciones de acceso y no reinicios del ordenador, bucles infinitos o crashes legendarios. La aplicación petaba y la podíamos volver a arrancar.


Nulabilidad en Java:


sábado, 22 de agosto de 2015

Hablemos de Kotlin

 Kotlin

Llevo algunas semanas trabajando en Kotlin. Y voy a empezar a escribir una serie de artículos sobre dicho lenguaje, su ecosistema y cosas relacionadas.

¿Qué es Kotlin?

Kotlin es un lenguaje de programación fuertemente tipado desarrollado por JetBrains (los creadores de IntelliJ IDEA).

Ha sido fuertemente influenciado por lenguajes como Scala o C#.

Targetea a la JVM (máquina virtual de Java 6) y a Javascript de forma nativa.

Ejemplos de Kotlin:

package hello

fun main(args: Array<String>) {
   println("Hello World!")
}

Ecosistema de Kotlin:

Es 100% interoperable con Java y permite proyectos mixtos mezclando código Java con código Kotlin. Como targetea a Java 6, es compatible con Android. Con iOS utilizando RoboVM. Utilizando GWT se puede también mezclar código Java con Kotlin para targetear a Javascript. Y con código Kotlin puro se puede targetear a Javascript directamente sin GWT. Es probable que con IKVM se pueda targetear a .NET, incluyendo Windows 10 y Windows Phone y Unity.

Carencias:

Tiene muchas menos características que Scala, pero es mucho más familiar, y ha sido diseñado para poder tener un tooling excelente acompañado con mejores tiempos de compilación que Scala. De hecho uno de los motivos que les llevó a desarrollar en Kotlin es porque los tiempos de compilación de Scala eran inaceptables para ellos.

A diferencia de Swift y por targetear a la JVM funciona con GC en vez de con ARC. Con sus ventajas y desventajas.

No tiene aliasing de tipos, casteos implícitos, ni duck typing.

Casos de uso:

Kotlin es ideal para desarrollos basados en JVM y para hacer aplicaciones de Android.
Kotlin es un lenguaje moderno y una buena elección en general.
Si te funciona bien Scala no ofrece muchos motivos.
Si estás en Java u otros lenguajes de pasada generación, el salto es enorme y la productividad aumentará un montón. Además es ameno de escribir y de trabajar con él.

Características del lenguaje y bondades:


viernes, 13 de junio de 2014

Followup

Llevaba bastante tiempo sin escribir por aquí.

He estado unos meses sabáticos de descanso y desconexión fuera del trabajo, haciendo lo que me rotaba, jugando y finiquitando algunos asuntos personales. Dejé de ser autónomo, y pronto estaré empadronado donde llevo ya viviendo independizado más de un año.

Tengo unos cuantos proyectos en standby y me gustaría retomarlos poco a poco, a la vez que voy cerrando otros. Pero siempre centrándome en mí, y disfrutando de lo que hago. Sin compromisos de tiempos, con calma y nunca con más de dos proyectos personales a la semana.

También me gustaría volver a retomar el escribir los artículos técnicos que solía escribir. Tengo pendientes algunos temas interesantes y en este tiempo han ido saliendo muchas cosas sobre las que vale la pena escribir.

Así que: stay tuned.

miércoles, 12 de marzo de 2014

Typescript, nodejs, generadores, harmony, q, taskjs y autocompletado

Introducción:

Últimamente he estado probando y experimentando con algunas tecnologías interesantes: virtualización a nivel de sistema operativo: chroot / lxc / docker. He estado experimentando también con heroku y monhohq. Y hace tiempo estuve experimentando con node-webkit y cross-walk y traceur compiler.

Este post lo escribo a poco de que salga nodejs 0.12, y typescript 1.0 y tras haberle dado otra oportunidad a dart en su versión 1.1 con muchas expectativas y con un resultado algo decepcionante. Con generadores implementados en v8 y disponibles en node.js a partir de la 0.11, y con task.js y q de por medio, habiendo adquirido mucha más experiencia con promesas, señales y streams, y con las promesas ya propuestas en el draft de harmony.

sábado, 1 de junio de 2013

Haxe3 + Starling + Continuation + Air

La metaprogramación de haxe es tan potente que permite modificar el AST en tiempo de compilación directamente desde haxe (código que se ejecuta en tiempo de compilación para modificar el AST de la compilación). Esto permite que se puedan crear pseudolenguajes, o que puedas programar en haxe y generar shaders de opengl. Pero lo que me gustaría comentar ahora es el proyecto continuation. Básicamente convierte código lineal en código asíncrono añadiendo cierta metainformación a la clase y a los métodos que lo van a usar de forma que se preprocese el código y se genere código asíncrono.

Desde Haxe3 además se pueden cargar archivos .SWC fácilmente.



jueves, 30 de mayo de 2013

Promesas

La programación asíncrona en JavaScript y especialmente en Node.JS ha estado basada principalmente en callbacks. Le pasas a la función que estás llamando un callback que ejecutará cuando termine de procesar lo que tenga que hacer. Esto llevaba a una pirámide de código inmanejable. La pirámide de código hace que procesar código asíncrono con bucles, o flujo condicional acabe siendo tedioso, además de ser muy propenso a errores ya que la gestión de errores se suele hacer pasando un parámetro con un posible error y otro parámetro con un valor. function(err, value) { }. Si se lanzan excepciones que no se gestionan dentro del código, se dejan de llamar a los callbacks esperados y se rompe el flujo; con lo que hace que todo sea extremadamente frágil.

Promises/A, Q, y asíncrono lineal con generadores

Con las promesas cambiamos el flujo. De funciones de tipo function myAsyncFunction<T>(...params:any[], done: (err:Error, value:T) => void) (que tienen un callback para seguir con el flujo y devuelven void) pasamos a funciones del tipo function myAsyncFunction<T>(...params:any[]) : Promise<T> (que ya no tienen el callback y lo que hacen es devolver una Promise).
Una promise es algo similar a un Event Listener, solo que no podemos hacer un dispatch y únicamente nos podemos registrar a un evento: obtener valor y obtener un error.

interface IDeferred<T> {
    resolve(value?: T): void;
    reject(err: Error): void;
    get promise(): IPromise<T>;
}

interface IPromise<T> {
    then(onResolved: (value: T) => void, onError?: (err: Error) => void, onProgress?: () => void) : IPromise<T>;
}

Básicamente cuando queremos convertir un código funcionando con callbacks tradicionales al sistema de promesas, lo que hacemos es generar un Deferred, que contiene los métodos para continuar el flujo con un valor o con un error y devolvemos la promesa vinculada al deferred, que únicamente tiene un método then, que ejecutará los callbacks que le pasamos cuando la llamamos cuando el deferred se resuelve o se rechaza. El método then devuelve otra promesa, que se lanzará cuando se complete el then actual.
De esta forma un método delay/sleep hecho con promesas quedaría así:

function sleep(timeInMilliseconds: number) : IPromise<any> {
    var deferred = new Deferred();
    setTimeout(function() {
        deferred.resolve();
    }, timeInMilliseconds);
    return deferred.promise;
}

sleep(1000).then(function() {
     alert('1 second passed');
});

Task.js permite utilizar los generadores bidireccionales de Harmony y el funcionamiento de las promesas para hacer una programación de procesos/tareas/actores/green threads/minithreads  cooperativos/multitarea no preemptiva. Esto se consigue pausando la ejecución y mandando/"generando" desde el generador una promesa. El gestor de tareas se suscribe a la promesa, y retoma el generador cuando la promesa se resuelve o se rechaza; mandando un valor de vuelta al generador, o generando una excepción dentro del contexto del generador.

martes, 28 de mayo de 2013

Generadores

Hace poco he escrito sobre que V8 ya soporta generadores en el bleeding_edge y que se pueden usar ya desde node con las últimas versiones inestables y que con eso se podrá escribir código asíncrono lineal desde javascript (sin anidar millones de funciones).

¿Qué son los generadores?

Enlace a la wikipedia: http://en.wikipedia.org/wiki/Generator_(computer_programming)

Básicamente un generador es como un iterador pero implementado como una función que va generando valores que otra función consume. Por ejemplo, podemos tener una función que genera un listado infinito de números primos. Podríamos hacer una función que generase un array con un montón de números primos, pero además de que ocuparía bastante memoria si generamos una lista grande, la lista sería limitada. Hay lenguajes que soportan la interfaz Iterable que permite crear una clase con un método que se va llamando en cada paso.