ADA#

Introducción#

Hace unas semanas, un compañero me mencionó Ada, un lenguaje que conocía vagamente por su rapidez y sus aplicaciones en la industria aeroespacial, especialmente en el desarrollo de aviones. Con este mínimo conocimiento, me adentré en el mundo de Ada.

Mi curiosidad creció al notar la escasez de recursos informales para aprender el lenguaje, como videos o tutoriales básicos. Encontré listas de reproducción en YouTube incompletas y blogs que solo llegaban a cubrir temas básicos como bucles. Sorprendentemente, ni siquiera encontré cursos en plataformas populares como Udemy o Coursera. Esto podría desanimar a cualquiera, pero en mi caso, me lo tomé como un reto y decidí explorar este lenguaje tan poco mainstream.

Primeros pasos#

Como suele ser habitual al aprender un nuevo lenguaje, lo primero que hice fue acudir a la documentación oficial. Con un manual de referencia y la guía de AdaCore en mano, empecé a dar mis primeros pasos.

HOLA MUNDO#

La primera impresión que me llevé al escribir un hola mundo fue que Ada tenía un estilo algo rústico, similar a Pascal, con sus procedures, begin y end. También noté un formato de indentación parecido al de Python. No encontré aquí la complejidad que a veces aparece en otros lenguajes, como Java, al escribir un programa simple. Esto me dio confianza para continuar.

Funciones#

Con un poco de confianza, decidí avanzar rápidamente y me sumergí en el tema de las funciones. Aquí también Ada me recordó a Pascal, especialmente con la distinción entre procedure (que no devuelve nada) y function (que sí devuelve un valor). La diferencia está en que, en Ada, el tipo de retorno se coloca al final de la función, en contraste con lenguajes como C, donde aparece al principio. Implementé algunas funciones simples para operaciones matemáticas básicas, sin demasiadas sorpresas en este apartado.

Recursividad#

Aunque la recursividad no suele ser popular entre los programadores, siempre he encontrado algo estéticamente interesante en su uso, y es un tema que suelo probar al aprender un lenguaje nuevo.

La recursividad en Ada no presentó problemas, hasta que intenté calcular números altos en la sucesión de Fibonacci. Para números pequeños, todo funcionaba bien; sin embargo, al llegar a valores más altos, encontré un error debido a la limitación en el tamaño de los enteros. Buscando una solución, descubrí el paquete Big Numbers, pero al intentar compilarlo, me apareció un error indicando que el paquete no existía. Esto me llevó a investigar Alire, el gestor de paquetes de Ada, y aunque no solucionó mi problema en ese momento, fue mi primera introducción a esta herramienta.

Alire#

En mi repositorio hay una rama llamada “Alire”, aunque realmente aún no he profundizado en el uso de este gestor de paquetes. A continuación, te comparto mis primeras impresiones sobre Alire.

Para empezar, Alire es un gestor de paquetes para Ada. Si tienes experiencia con Rust, notarás rápidamente que Alire es comparable a Cargo, aunque con algunas diferencias que lo hacen interesante. Sin embargo, la comunidad de Alire es relativamente pequeña, y eso se refleja en la cantidad y variedad de paquetes disponibles. Al explorar la lista de crates en su sitio web, da la sensación de que muchos paquetes son demasiado específicos, y la falta de una comunidad grande y diversa limita las opciones y la amplitud de aplicaciones.

Al comparar con crates.io de Cargo, la diferencia es clara. La web de Cargo es mucho más amigable, con un buscador avanzado y etiquetas que facilitan encontrar paquetes de interés, sin depender tanto del nombre o de una descripción exacta. En Alire, el buscador a veces resulta menos eficiente, y la navegación entre las categorías no es tan intuitiva; aunque, curiosamente, usar ctrl + f y las etiquetas manualmente puede resultar más práctico.

Además, he experimentado algunos inconvenientes al compilar con Alire. Aunque agradezco los errores de programación y advertencias importantes, los warnings de estilo a veces pueden resultar excesivos, sobre todo en proyectos personales donde no es tan relevante seguir un formato específico. Entiendo que este tipo de advertencias pueden ser útiles para aprender las convenciones del lenguaje, pero en mi caso, prefiero enfocarme en la funcionalidad antes que en el estilo. Quizás exista alguna forma de desactivar estos warnings de estilo, pero aún no he investigado a fondo.

En resumen, creo que Alire tiene potencial, pero la falta de comunidad limita el desarrollo de un ecosistema más amplio y robusto. Con una comunidad más activa, seguramente estas limitaciones se irían superando gradualmente.

Semáforos#

Este proyecto es el antes mencionado que se llama Alire pero que no aprovecha nada de este gestor de paquetes. Mi finalidad en este código era explorar tanto la concurrencia como el paralelismo de ADA, el cual, al buscar información sobre otros temas, aparentemente era de los puntos más fuertes que tenía el lenguaje. Lograr que todo funcionara correctamente no fue sencillo; como mencioné anteriormente, los warnings de estilo de Alire, aunque útiles en otros contextos, no ayudaban a identificar los problemas reales de funcionamiento. Sin embargo, con perseverancia, logré construir una simulación funcional de un sistema de tráfico con semáforos y vehículos. A continuación, algunos aspectos destacados del proyecto:

  • Implementé tareas para los semáforos y los vehículos, de manera que cada uno pudiera monitorear y coordinarse con el estado de los demás.
  • Para que los vehículos pudieran cruzar la intersección sin colisiones, usé un tipo protegido llamado Intersection. Los tipos protegidos en Ada permiten el acceso concurrente controlado a recursos compartidos, lo cual es esencial en sistemas donde múltiples procesos pueden acceder a un mismo recurso.
  • Para gestionar el cambio de estados en el semáforo y recibir las solicitudes de los vehículos, utilicé entradas en la tarea TrafficLight como Change_To_Green y Change_To_Red. Mediante la sentencia select, pude hacer que el semáforo aceptara estas llamadas de entrada según su estado actual.

Detector de movimiento#

En este proyecto finalmente decidí dejar el uso de Alire para otra ocasión y considerarlo un aprendizaje a futuro. La idea de implementar un detector de movimiento surgió por dos motivos: el primero fue notar, al explorar la página de crates de Alire, que no había algo comparable a OpenCV; el segundo fue recordar un proyecto anterior donde integré código C en Rust usando Cargo. Si bien esto introdujo código inseguro y un tanto contrario a la filosofía de Rust, fue una buena oportunidad para experimentar. Esta vez quise intentar algo nuevo y explorar las posibilidades de Ada en combinación con OpenCV.

Mi enfoque consistió en identificar qué funciones de OpenCV eran necesarias para implementar un detector de movimiento en C++ y, a partir de allí, desarrollar un wrapper que pudiera integrarse con Ada. Este wrapper maneja la creación del detector, la captura de fotogramas y las operaciones de procesamiento de movimiento. A través de pragma Import expuse las funciones del wrapper de C++ a Ada, permitiéndome trabajar con estas funcionalidades de OpenCV directamente desde el código en Ada. Esta experiencia me ayudó a comprender cómo gestionar la interoperabilidad entre Ada y C++, especialmente en proyectos de cierto nivel de complejidad.

Durante el desarrollo, también fue clave aprender a coordinar tareas concurrentes. La tarea Save_Motion se ejecuta en paralelo, guardando los fotogramas que contienen movimiento sin interferir con la captura en tiempo real. Ada facilitó esta estructura mediante el uso de tareas, y aprendí mucho sobre cómo gestionar sistemas en tiempo real. La sincronización de recursos compartidos fue otro desafío que Ada ayudó a simplificar, especialmente al coordinar el acceso seguro a los recursos de OpenCV.