Los límites de la interoperabilidad Elm/JS

Muchos lenguajes tienen una “interfaz de funciones foráneas” (FFI por su sigla en inglés) que te permite vincular directamente con funciones del lenguaje subyacente. Por ejemplo, Scala puede llamar funciones de Java directamente. Lo mismo ocurre con Clojure y Java, Python y C, Haskell y C, y muchos otros.

Elm no tiene una interfaz de funciones foráneas tradicional con JavaScript. No es posible llamar funciones arbitrarias de JavaScript en cualquier momento. Es una limitación que trae beneficios que mucha gente prefiere, pero no es para cualquiera. Si te encuentras evaluando si usar Elm con fines comerciales, te recomiendo que revises estos ejemplos de interoperabilidad para saber si con flags, puertos y elementos personalizados tienes cubiertas tus necesidades.

¿Por qué Elm tomó una decisión diferente en comparación con otros lenguajes?

Ventajas y desventajas

Los puertos son un caso atípico en la historia de los lenguajes de programación. Hay dos principales estrategias para la interoperabilidad, y Elm no adoptó ninguna de ellas:

  1. Interfaz de función foránea (FFI). Permite crear vínculos directos hacia funciones en el lenguaje subyacente. Por ejemplo, Scala puede llamar funciones de Java directamente. Lo mismo ocurre con Clojure y Java, Python y C, Haskell y C, y muchos otros. Esta también es una estrategia que ha resultado ser muy efectiva.

Estos caminos son atractivos para facilitar un crecimiento rápido y tener máxima flexibilidad, pero no son ideales para Elm por dos razones:

  1. Pérdida de garantías. Una de las mejores cosas sobre Elm es que hay categorías enteras de problemas de las que simplemente no te tienes que preocupar. No hay excepciones sorpresa para capturar, y las funciones no pueden mutar datos en forma sorpresiva. Creo que este es el principal valor de Elm por sobre otras alternativas, pero si pudiéramos llamar código JS directamente, todo se evapora. ¿Este paquete produce excepciones en tiempo de ejecución? ¿Cuándo? ¿Muta los valores que le paso? ¿Necesito chequear? ¿El paquete produce efectos secundarios? ¿Se comunica con servidores externos? ¿Escribe passwords en sus logs? Un gran número de usuarios de Elm tienen interés en Elm justamente porque con el lenguaje no necesitan cubrirse las espaldas de esta manera.
  2. Avalancha de paquetes. Hay una gran demanda de copias directas de interfaces de JavaScript hacia Elm. En los dos años previos a que existiera elm/html, estoy seguro de que alguien hubiera escrito una interfaz para usar jQuery si fuera posible. Esto ya ha ocurrido con otros lenguajes funcionales tipados que compilan a JS, pero que tienen una estrategia más tradicional de interoperabilidad. Hasta donde sé, este tipo de situación es más o menos única en lenguajes que compilan a JS. No existe esa presión en Python, por ejemplo, así que probablemente es un problema producto de la cultura e historia del ecosistema de JavaScript en específico.

Dados estos problemas, los puertos y los elementos personalizados son atractivos porque nos permiten lograr cosas usando JavaScript, sin sacrificar los beneficios de Elm. Ideal. Pero por otro lado, también significa que Elm no puede simplemente colgarse del ecosistema JavaScript para ganar en librerías más rápidamente. Si adoptamos una visión más a largo plazo, creo que es una buena estrategia. Como consecuencia:

  1. Los paquetes están diseñados para Elm. Mientras la comunidad de Elm adquiere experiencia y confianza, empezamos a ver nuevas y propositivas estrategias para enfrentar la diagramación y la visualización de datos que se acoplan perfectamente con la Arquitectura Elm y con el ecosistema en general. Anticipo que esto se repetirá con muchos otros problemas.
  2. El código es portátil. Si Elm llegara un día a compilar a x86 o WebAssembly, todo el ecosistema seguiría funcionando, ¡pero más rápido! Los puertos garantizan que todos los paquetes estén escritos completamente en Elm, y el lenguaje mismo está diseñado para que nuevos destinos de compilación sean viables.
  3. Los paquetes son más seguros. Lenguajes como JavaScript tienen serios problemas de seguridad con sus paquetes. No es infrecuente oir noticias sobre robo de credenciales o de llaves de API, y esto causa un costo permanente en auditoría de todos estos paquetes. Es hasta posible instalar un keylogger en window. Los paquetes de Elm garantizan que categorías completas de vulnerabilidades simplemente no pueden ser explotadas, lo que reduce el costo de la auditoría y los riesgos de seguridad en general.
  4. Es más fácil de optimizar. El estilo del código generado ha cambiado considerablemente de versión a versión. Por ejemplo, en la versión 0.19 pudimos reducir dramáticamente el tamaño de los exportables (1) al generar código que funciona mejor con los minificadores de JavaScript, y (2) al usar distintas maneras de representar tipos personalizados dependiendo del nivel de optimización elegido. Seguramente volveremos a hacer cambios para permitir la subdivisión de archivos o si encontramos una convención de llamada más rápida para las funciones currificadas. Además, el compilador puede asumir que todo el código es puro, lo que le permite manipularlo mucho más que otros compiladores. Si nos casáramos con una convención de llamada específica haría que muchas de estas optimizaciones sean imposibles.

Es un camino más largo y arduo, pero los lenguajes pueden vivir mucho más de 30 años. Tienen que sostener a equipos y empresas por décadas, y cuando pienso en cómo será Elm en 20 o 30 años, las ventajas otorgadas por los puertos me permiten ser muy optimista. Mi charla “¿Qué es el éxito?” (en inglés) empieza lenta, pero eventualmente toca este tema.

Y repito, este no es un camino para cualquiera. Hay muchos lenguajes alternativos que tienen una interfaz de función foránea tradicional, y te sugiero que los investigues si crees que serían una mejor opción. ¿El ecosistema de paquetes es igual de coherente? ¿Tendrás más excepciones en tiempo de ejecución? Tal vez. Pero tal vez la flexibilidad vale la pena para ti. Así que te animo a que revises estos ejemplos de interoperabilidad para decidir si las flags, los puertos y los elementos personalizados cubren todas tus necesidades. Esto es especialmente importante si estás considerando usar Elm con fines comerciales.

results matching ""

    No results matching ""