• No se han encontrado resultados

Elixir [2,3,101,102] es un lenguaje funcional, concurrente y de propósito general, que se

ejecuta en la máquina virtual de Erlang [69,103], más conocida como la BEAM. Como es de

esperar, todo lo que se puede hacer en Erlang, se puede hacer en Elixir, y viceversa.

El entorno de ejecución de Elixir es una instancia de la BEAM. Cuando se inicia el sistema, Erlang toma el control. Se crea un proceso del sistema operativo, para la instancia de la BEAM, y todo ejecuta dentro de ese proceso. La mejor forma de encontrar el citado proceso es buscar,

1 $ iex -pa /path/a/mi/codigo -pa path/a/otro/codigo Listing B.3: Intérprete interactivo de Elixir

por ejemplo, mediante el comandotopo similar, un proceso con el nombrebeam. Es impor-

tante tener en cuenta que, una vez que el sistema está iniciado, la máquina virtual de Erlang hace un seguimiento de todos los módulos que se encuentran cargados en memoria. Cuando se invoca una función de un módulo, lo primero que hace la BEAM es comprobar si el módulo ya está cargado. Si es así, ejecuta el código correspondiente a la función. En caso contrario, busca el fichero compilado del módulo (cada módulo compilado reside en un fichero con la

extensión.beam) y lo carga para, posteriormente, ejecutar el código de la función invocada. Si

se definen múltiples módulos dentro de un mismo fichero fuente, el compilador generará un

fichero.beampara cada módulo. El intérprete interactivo de Elixir puede iniciarse fácilmente

invocandoiexB.3.

Un fichero fuente puede definir uno o varios módulos, en su interior, pero también pue- de contener algún código fuera de esos módulos. Supongamos que dicho fichero se llama

mis_modulos.ex. Cuando nosotros ejecutamos “elixir --no-halt mis_modulos.ex”, se

inicia una instancia de la BEAM. Posteriormente, el fichero es compilado en memoria y los módulos resultantes se cargan en la máquina virtual. El código que reside fuera de los mó-

dulos es interpretado y no se genera ningún fichero.beamen el disco. Una vez hecho todo

esto, la instancia de la BEAM debería detenerse, pero sigue viva porque hemos especificado

la opción--no-halt.

Actualmente, Elixir sigue un esquema de versionado semántico [104][105], con solo una

“major release” [AnexoA] liberada hasta la fecha. En resumen, la versión actual de su API

pública es, totalmente, retrocompatible con la primera versión liberada de la API. Algunos de los aspectos más destacables del lenguaje son los siguientes:

• Las estructuras de datos, en Elixir, son inmutables. Esto permite un código más cla- ro. Una función puede devolver una versión modificada de su entrada, que reside en otra posición de memoria. La versión modificada compartirá tanta memoria como sea posible con la original.

• Es un lenguaje con tipado dinámico. El tipo de una variable lo determina el valor que posee.

• Es un lenguaje que hace un fuerte uso de concordancia de patrones (pattern matching) y

expresiones regulares. Si tenemos algo tal comobaraja = {:parse, :error, :be-

fore, :la, :sota, :de, :bastos}, el operador=se llamamatch. El lado izquierdo

a un término (term). En Elixir, se empleatermcomo una abreviatura con el significado de “cualquier tipo”. En tiempo de ejecución, se hace concordar el lado izquierdo con lo

que hay en el lado derecho. En el ejemplo, hacemos concordar la variablebarajacon el

término{:parse, :error, :before, :la, :sota, :de, :bastos}. Como una

variable siempre concuerda con el término del lado derecho, barajaquedará ligada

a dicho término. No debe confundirse la concordancia de patrones con la asignación, puesto que se trata de un concepto más complejo.

• La programación defensiva brilla por su ausencia. Eltry/catchno está muy bien visto en

la comunidad de usuarios. La tolerancia a fallos se suele dejar en manos de procesos su- pervisores que conforman árboles de supervisión y definen estrategias de recuperación a seguir.

• Admite intercambio de código en caliente. Esto es, no es necesario detener la aplicación para aplicar una actualización de código.

• Se pueden utilizar librerías de Erlang. Una gran ventaja, ya que pone a disposición del desarrollador el inmenso OTP (middleware, herramientas y librerías escritas para Er- lang).

• Manejo fácil de la concurrenciaB.10. Crear procesos es muy barato y sincronizarlos,

mediante paso de mensajes, prácticamente trivial.

• Elixir, al utilizar la máquina virtual de Erlang, se muestra como una alternativa perfec- tamente viable para el desarrollo de sistemas distribuidos y, al igual que Erlang, escala muy bien. Los sistemas Elixir, de forma análoga a lo que es común en sus homólogos Erlang, suelen tener una alta disponibilidad.

• El lenguaje posee una sintaxis muy fácil e intuitiva (azúcar sintáctico). Dicha sintaxis permite no escribir excesivo código y, el que se escribe, es posible hacerlo de una forma muy clara.

Releases: Un directorio autocontenido que alberga la aplicación, todas sus dependencias

y la máquina virtual de Erlang. Una vez que está ensamblada, lareleasepuede ser em-

paquetada y desplegada a cualquier objetivo, siempre que tenga la misma versión del sistema operativo.

• Mix: Una completísima herramienta para la gestión del proyecto, en línea de comandos. Genera plantillas/esqueletos, construye el proyecto, genera la documentación, gestiona

dependencias, ejecuta las pruebas, etc. La capacidad descripting, admitida por Mix, es

uno de las grandes fortalezas de Elixir. Esta herramienta se suele emplear para el flujo

• Soporta el gestor de paquetes Hex [106]. Un clásico para ecosistemas Erlang.

• Umbrella: Permite dividir un proyecto más o menos grande en múltiples aplicaciones. Así se tiende a simplificar una lógica compleja en partes más simples.

• El lenguaje posee un potente sistema de macros, que favorecen la extensibilidad del mismo, a la vez que permiten el desarrollo de lenguajes específicos del dominio con suma facilidad. Una macro no deja de ser código Elixir que recibe una representación del código de entrada Elixir, parseado, y retorna una versión alternativa de dicho código. Las macros permiten realizar transformaciones del código en tiempo de compilación y permiten modificar la semántica del código de entrada a la macro.

Protocols: El polimorfismo no es otra cosa que la decisión, en tiempo de ejecución, refe-

rente a qué código ejecutar en función de la naturaleza de los datos de entrada. En Elixir,

una de las maneras de obtener el polimorfismo es haciendo uso deprotocols. Unprotocol

es un módulo que declara ciertas funciones sin implementarlas. Posteriormente, se debe

realizar una implementación delprotocolpara distintos tipos de datos.

ets: Elixir implementa la memoria compartida entre procesos en forma de tablasets.

• Todo proceso en Elixir tiene un diccionario de proceso, clave-valor, en el que se pueden almacenar valores que el proceso podrá acceder en cualquier momento. No obstante, su uso genera mucha controversia, en la comunidad Elixir, puesto que se argumenta que emplear dicho diccionario hace el código más difícil de seguir y, por tanto, de compren- der.

Elixir es un lenguaje funcional y la mayor parte de la programación, bajo el mismo, con- siste en escribir módulos de funciones. Las funciones son ciudadanos de primera clase. Si se desea seguir cualquier otro tipo de paradigma, entonces no es la opción más aconsejable.

No hay tipo booleano, ni nulos. En su lugar se utilizan los átomos (constantes cuyo valor es su nombre) true, false y, por ejemplo, nil.

No hay tipo “cadena de caracteres”. En su lugar se utiliza el tipobinary, que representa

secuencias debytescon codificación Unicode UTF-8.

El tipotuplapermite agrupar un pequeño número de campos de tamaño fijo. Los elemen-

tos se almacenan de forma contigüa en memoria. Ej. {:ok, “ok_msg”}.

El tipolistase usa para colecciones de tamaño variable. Ej. [1 | [2, 3]].

El tipoMapes una estructura de datos clave-valor. Ej. %{:a => 1, 2 => :b}.

A modo de aclaración, conviene destacar que un proceso en Elixir no tiene, absolutamente, nada que ver con un proceso/hilo del sistema operativo. En Elixir, un proceso es una primitiva básica de concurrencia, y no es para nada raro ver millones de estos procesos ejecutando en

Concurrencia = 2 colas & 1 máquina de café

Paralelismo = 2 colas & 2 máquinas de café

Figura B.10: Concurrencia vs. Paralelismo

la BEAM. La BEAM dispone de sus propios planificadores para distribuir los procesos sobre los núcleos de la CPU.

Erlang y Elixir no son, precisamente, lenguajes rápidos. Por tanto, si el desarrollo requiere mucha carga de CPU, definitivamente BEAM no es el camino a seguir. Otros lenguajes como C o C++, que compilan a código nativo, son mucho más rápidos, con diferencia. Por tanto, es difícil encontrar librerías pensadas para trabajos CPU intensivos, del estilo de Apache Lu-

cene [107], escritas para Elixir. Con esto no queremos decir que está todo perdido. Existen

soluciones como delegar dichas tareas en un servidor externo y escribir un módulo de co-

municación para Elixir o, incluso, usar el sistema deports que Elixir suministra. El módulo

Port [108], de Elixir, nos dota de funciones para iniciar procesos del sistema operativo ex-

ternos a la máquina virtual de Erlang, al mismo tiempo que nos permite comunicarnos con dicho procesos mediante paso de mensajes. Este mecanismo nos provee de una forma muy fácil de interaccionar, por ejemplo, con programas C o comandos del sistema operativo. Por supuesto, es recomendable tener unos conocimientos mínimos sobre sistemas de ficheros y, más concretamente, sobre descriptores.

Por otro lado, la velocidad no lo es todo. Por ello, Erlang/Elixir se centran más en man-

tener el rendimiento estabilizado, dentro de unos límites, que en situarse en eltop tende los

lenguajes más veloces.

En lo referente al tiempo de respuesta de los sistemas basados en Elixir, suele ser bueno, en condiciones de carga normales; a no ser que el código escrito sea manifiestamente ineficiente. El ecosistema Elixir es pequeño, aunque con la ayuda de Erlang su tamaño aumenta sensi-

blemente. No obstante, si lo que se desea, a la hora de realizar un proyecto, es disponer de un gran número de alternativas entre las cuales elegir, es más razonable enfocarse en lenguajes tales como JavaScript.